1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
/*
* Copyright (C) 2015-2018 Team Kodi
* This file is part of Kodi - https://kodi.tv
*
* SPDX-License-Identifier: GPL-2.0-or-later
* See LICENSES/README.md for more information.
*/
#pragma once
#include "FileItem.h"
#include "URL.h"
#include "utils/CharsetConverter.h"
#include "utils/StringUtils.h"
#include "utils/URIUtils.h"
#include <string>
#include <utility>
#include <vector>
namespace XFILE
{
/**
* \brief Method definition to convert an entry to a CFileItemPtr.
*
* \param entry The entry to convert to a CFileItemPtr
* \param label The label of the entry
* \param path The path of the entry
* \param isFolder Whether the entry is a folder or not
* \return The CFileItemPtr object created from the given entry and data.
*/
template<class TEntry>
using DirectorizeEntryToFileItemFunction = CFileItemPtr(*)(const TEntry& entry, const std::string& label, const std::string& path, bool isFolder);
template<class TEntry>
using DirectorizeEntry = std::pair<std::string, TEntry>;
template<class TEntry>
using DirectorizeEntries = std::vector<DirectorizeEntry<TEntry>>;
/**
* \brief Analyzes the given entry list from the given URL and turns them into files and directories on one directory hierarchy.
*
* \param url URL of the directory hierarchy to build
* \param entries Entries to analyze and turn into files and directories
* \param converter Converter function to convert an entry into a CFileItemPtr
* \param items Resulting item list
*/
template<class TEntry>
static void Directorize(const CURL& url, const DirectorizeEntries<TEntry>& entries, DirectorizeEntryToFileItemFunction<TEntry> converter, CFileItemList& items)
{
if (url.Get().empty() || entries.empty())
return;
const std::string& options = url.GetOptions();
const std::string& filePath = url.GetFileName();
CURL baseUrl(url);
baseUrl.SetOptions(""); // delete options to have a clean path to add stuff too
baseUrl.SetFileName(""); // delete filename too as our names later will contain it
std::string basePath = baseUrl.Get();
URIUtils::AddSlashAtEnd(basePath);
std::vector<std::string> filePathTokens;
if (!filePath.empty())
StringUtils::Tokenize(filePath, filePathTokens, "/");
bool fastLookup = items.GetFastLookup();
items.SetFastLookup(true);
for (const auto& entry : entries)
{
std::string entryPath = entry.first;
std::string entryFileName = entryPath;
StringUtils::Replace(entryFileName, '\\', '/');
// skip the requested entry
if (entryFileName == filePath)
continue;
// Disregard Apple Resource Fork data
std::size_t found = entryPath.find("__MACOSX");
if (found != std::string::npos)
continue;
std::vector<std::string> pathTokens;
StringUtils::Tokenize(entryFileName, pathTokens, "/");
// ignore any entries in lower directory hierarchies
if (pathTokens.size() < filePathTokens.size() + 1)
continue;
// ignore any entries in different directory hierarchies
bool ignoreItem = false;
entryFileName.clear();
for (auto filePathToken = filePathTokens.begin(); filePathToken != filePathTokens.end(); ++filePathToken)
{
if (*filePathToken != pathTokens[std::distance(filePathTokens.begin(), filePathToken)])
{
ignoreItem = true;
break;
}
entryFileName = URIUtils::AddFileToFolder(entryFileName, *filePathToken);
}
if (ignoreItem)
continue;
entryFileName = URIUtils::AddFileToFolder(entryFileName, pathTokens[filePathTokens.size()]);
char c = entryPath[entryFileName.size()];
if (c == '/' || c == '\\')
URIUtils::AddSlashAtEnd(entryFileName);
std::string itemPath = URIUtils::AddFileToFolder(basePath, entryFileName) + options;
bool isFolder = false;
if (URIUtils::HasSlashAtEnd(entryFileName)) // this is a directory
{
// check if the directory has already been added
if (items.Contains(itemPath)) // already added
continue;
isFolder = true;
URIUtils::AddSlashAtEnd(itemPath);
}
// determine the entry's filename
std::string label = pathTokens[filePathTokens.size()];
g_charsetConverter.unknownToUTF8(label);
// convert the entry into a CFileItem
CFileItemPtr item = converter(entry.second, label, itemPath, isFolder);
item->SetPath(itemPath);
item->m_bIsFolder = isFolder;
if (isFolder)
item->m_dwSize = 0;
items.Add(item);
}
items.SetFastLookup(fastLookup);
}
}
|