summaryrefslogtreecommitdiffstats
path: root/xbmc/addons/kodi-addon-dev-kit/include/kodi/Filesystem.h
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/addons/kodi-addon-dev-kit/include/kodi/Filesystem.h')
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/Filesystem.h1490
1 files changed, 1490 insertions, 0 deletions
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/Filesystem.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/Filesystem.h
new file mode 100644
index 0000000..3222e8b
--- /dev/null
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/Filesystem.h
@@ -0,0 +1,1490 @@
1#pragma once
2/*
3 * Copyright (C) 2005-2017 Team Kodi
4 * http://kodi.tv
5 *
6 * This Program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This Program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Kodi; see the file COPYING. If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#include "AddonBase.h"
23
24#include <map>
25
26#if !defined(_WIN32)
27 #include <sys/stat.h>
28 #if !defined(__stat64)
29 #define __stat64 stat64
30 #endif
31#endif
32#ifdef _WIN32 // windows
33#ifndef _SSIZE_T_DEFINED
34 typedef intptr_t ssize_t;
35 #define _SSIZE_T_DEFINED
36#endif // !_SSIZE_T_DEFINED
37#endif
38
39#ifndef S_ISDIR
40 #define S_ISDIR(mode) ((((mode)) & 0170000) == (0040000))
41#endif
42
43#ifndef S_ISLNK
44 #define S_ISLNK(mode) ((((mode)) & 0170000) == (0120000))
45#endif
46
47/*
48 * For interface between add-on and kodi.
49 *
50 * This structure defines the addresses of functions stored inside Kodi which
51 * are then available for the add-on to call
52 *
53 * All function pointers there are used by the C++ interface functions below.
54 * You find the set of them on xbmc/addons/interfaces/General.cpp
55 *
56 * Note: For add-on development itself this is not needed
57 */
58extern "C"
59{
60
61 struct VFSProperty
62 {
63 char* name;
64 char* val;
65 };
66
67 struct VFSDirEntry
68 {
69 char* label; //!< item label
70 char* title; //!< item title
71 char* path; //!< item path
72 unsigned int num_props; //!< Number of properties attached to item
73 VFSProperty* properties; //!< Properties
74 time_t date_time; //!< file creation date & time
75 bool folder; //!< Item is a folder
76 uint64_t size; //!< Size of file represented by item
77 };
78
79 typedef struct AddonToKodiFuncTable_kodi_filesystem
80 {
81 bool (*can_open_directory)(void* kodiBase, const char* url);
82 bool (*create_directory)(void* kodiBase, const char* path);
83 bool (*remove_directory)(void* kodiBase, const char* path);
84 bool (*directory_exists)(void* kodiBase, const char* path);
85 bool (*get_directory)(void* kodiBase, const char* path, const char* mask, VFSDirEntry** items, unsigned int* num_items);
86 void (*free_directory)(void* kodiBase, VFSDirEntry* items, unsigned int num_items);
87
88 bool (*file_exists)(void* kodiBase, const char *filename, bool useCache);
89 int (*stat_file)(void* kodiBase, const char *filename, struct __stat64* buffer);
90 bool (*delete_file)(void* kodiBase, const char *filename);
91 bool (*rename_file)(void* kodiBase, const char *filename, const char *newFileName);
92 bool (*copy_file)(void* kodiBase, const char *filename, const char *dest);
93
94 char* (*get_file_md5)(void* kodiBase, const char* filename);
95 char* (*get_cache_thumb_name)(void* kodiBase, const char* filename);
96 char* (*make_legal_filename)(void* kodiBase, const char* filename);
97 char* (*make_legal_path)(void* kodiBase, const char* path);
98 char* (*translate_special_protocol)(void* kodiBase, const char *strSource);
99
100 void* (*open_file)(void* kodiBase, const char* filename, unsigned int flags);
101 void* (*open_file_for_write)(void* kodiBase, const char* filename, bool overwrite);
102 ssize_t (*read_file)(void* kodiBase, void* file, void* ptr, size_t size);
103 bool (*read_file_string)(void* kodiBase, void* file, char *szLine, int iLineLength);
104 ssize_t (*write_file)(void* kodiBase, void* file, const void* ptr, size_t size);
105 void (*flush_file)(void* kodiBase, void* file);
106 int64_t (*seek_file)(void* kodiBase, void* file, int64_t position, int whence);
107 int (*truncate_file)(void* kodiBase, void* file, int64_t size);
108 int64_t (*get_file_position)(void* kodiBase, void* file);
109 int64_t (*get_file_length)(void* kodiBase, void* file);
110 double (*get_file_download_speed)(void* kodiBase, void* file);
111 void (*close_file)(void* kodiBase, void* file);
112 int (*get_file_chunk_size)(void* kodiBase, void* file);
113
114 void* (*curl_create)(void* kodiBase, const char* url);
115 bool (*curl_add_option)(void* kodiBase, void* file, int type, const char* name, const char* value);
116 bool (*curl_open)(void* kodiBase, void* file, unsigned int flags);
117 } AddonToKodiFuncTable_kodi_filesystem;
118
119} /* extern "C" */
120
121//==============================================================================
122/// \defgroup cpp_kodi_vfs_CFile_Defs Definitions, structures and enumerators
123/// \ingroup cpp_kodi_vfs_CFile
124/// @brief **Virtual file Server definition values**
125//------------------------------------------------------------------------------
126
127//==============================================================================
128///
129/// @ingroup cpp_kodi_vfs_CFile_Defs
130/// Flags to define way how file becomes opened with kodi::vfs::CFile::OpenFile()
131///
132/// The values can be used together, e.g. <b>`file.Open("myfile", READ_TRUNCATED | READ_CHUNKED);`</b>
133///
134typedef enum OpenFileFlags
135{
136 /// indicate that caller can handle truncated reads, where function returns
137 /// before entire buffer has been filled
138 READ_TRUNCATED = 0x01,
139
140 /// indicate that that caller support read in the minimum defined chunk size,
141 /// this disables internal cache then
142 READ_CHUNKED = 0x02,
143
144 /// use cache to access this file
145 READ_CACHED = 0x04,
146
147 /// open without caching. regardless to file type
148 READ_NO_CACHE = 0x08,
149
150 /// calcuate bitrate for file while reading
151 READ_BITRATE = 0x10,
152
153 /// indicate to the caller we will seek between multiple streams in the file
154 /// frequently
155 READ_MULTI_STREAM = 0x20,
156
157 /// indicate to the caller file is audio and/or video (and e.g. may grow)
158 READ_AUDIO_VIDEO = 0x40,
159
160 /// indicate that caller will do write operations before reading
161 READ_AFTER_WRITE = 0x80,
162
163 /// indicate that caller want to reopen a file if its already open
164 READ_REOPEN = 0x100
165} OpenFileFlags;
166//------------------------------------------------------------------------------
167
168//==============================================================================
169/// \ingroup cpp_kodi_vfs_CFile_Defs
170/// @brief Used CURL message types
171///
172typedef enum CURLOptiontype
173{
174 /// Set a general option
175 ADDON_CURL_OPTION_OPTION,
176 /// Set a protocol option
177 ADDON_CURL_OPTION_PROTOCOL,
178 /// Set User and password
179 ADDON_CURL_OPTION_CREDENTIALS,
180 /// Add a Header
181 ADDON_CURL_OPTION_HEADER
182} CURLOptiontype;
183//------------------------------------------------------------------------------
184
185//============================================================================
186///
187/// \ingroup cpp_kodi_vfs_CFile_Defs
188/// @brief Information about a file
189///
190struct STAT_STRUCTURE
191{
192 /// ID of device containing file
193 uint32_t deviceId;
194 /// Total size, in bytes
195 uint64_t size;
196#ifdef TARGET_WINDOWS
197 /// Time of last access
198 __time64_t accessTime;
199 /// Time of last modification
200 __time64_t modificationTime;
201 /// Time of last status change
202 __time64_t statusTime;
203#else
204 /// Time of last access
205 timespec accessTime;
206 /// Time of last modification
207 timespec modificationTime;
208 /// Time of last status change
209 timespec statusTime;
210#endif
211 /// The stat url is a directory
212 bool isDirectory;
213 /// The stat url is a symbolic link
214 bool isSymLink;
215};
216//------------------------------------------------------------------------------
217
218namespace kodi
219{
220namespace vfs
221{
222
223 //============================================================================
224 ///
225 /// \defgroup cpp_kodi_vfs_CDirEntry class CDirEntry
226 /// \ingroup cpp_kodi_vfs
227 ///
228 /// @brief **Virtual file server directory entry**
229 ///
230 /// This class is used as an entry for files and folders in
231 /// kodi::vfs::GetDirectory().
232 ///
233 ///
234 /// ------------------------------------------------------------------------
235 ///
236 /// **Example:**
237 /// ~~~~~~~~~~~~~{.cpp}
238 /// #include <kodi/Filesystem.h>
239 ///
240 /// ...
241 ///
242 /// std::vector<kodi::vfs::CDirEntry> items;
243 /// kodi::vfs::GetDirectory("special://temp", "", items);
244 ///
245 /// fprintf(stderr, "Directory have %lu entries\n", items.size());
246 /// for (unsigned long i = 0; i < items.size(); i++)
247 /// {
248 /// char buff[20];
249 /// time_t now = items[i].DateTime();
250 /// strftime(buff, 20, "%Y-%m-%d %H:%M:%S", gmtime(&now));
251 /// fprintf(stderr, " - %04lu -- Folder: %s -- Name: %s -- Path: %s -- Time: %s\n",
252 /// i+1,
253 /// items[i].IsFolder() ? "yes" : "no ",
254 /// items[i].Label().c_str(),
255 /// items[i].Path().c_str(),
256 /// buff);
257 /// }
258 /// ~~~~~~~~~~~~~
259 ///
260 /// It has the header \ref Filesystem.h "#include <kodi/Filesystem.h>" be included
261 /// to enjoy it.
262 ///
263 //@{
264 class CDirEntry
265 {
266 public:
267 //============================================================================
268 ///
269 /// @ingroup cpp_kodi_vfs_CDirEntry
270 /// @brief Constructor for VFS directory entry
271 ///
272 /// @param[in] label [opt] Name to use for entry
273 /// @param[in] path [opt] Used path of the entry
274 /// @param[in] folder [opt] If set entry used as folder
275 /// @param[in] size [opt] If used as file, his size defined there
276 ///
277 CDirEntry(const std::string& label = "",
278 const std::string& path = "",
279 bool folder = false,
280 int64_t size = -1) :
281 m_label(label),
282 m_path(path),
283 m_folder(folder),
284 m_size(size)
285 {
286 }
287 //----------------------------------------------------------------------------
288
289 //============================================================================
290 // @note Not for addon development itself needed, thats why below is
291 // disabled for doxygen!
292 //
293 // @ingroup cpp_kodi_vfs_CDirEntry
294 // @brief Constructor to create own copy
295 //
296 // @param[in] dirEntry pointer to own class type
297 //
298 CDirEntry(const VFSDirEntry& dirEntry) :
299 m_label(dirEntry.label ? dirEntry.label : ""),
300 m_path(dirEntry.path ? dirEntry.path : ""),
301 m_folder(dirEntry.folder),
302 m_size(dirEntry.size),
303 m_dateTime(dirEntry.date_time)
304 {
305 }
306 //----------------------------------------------------------------------------
307
308 //============================================================================
309 ///
310 /// @ingroup cpp_kodi_vfs_CDirEntry
311 /// @brief Get the directory entry name
312 ///
313 /// @return Name of the entry
314 ///
315 const std::string& Label(void) const { return m_label; }
316 //----------------------------------------------------------------------------
317
318 //============================================================================
319 ///
320 /// @ingroup cpp_kodi_vfs_CDirEntry
321 /// @brief Get the optional title of entry
322 ///
323 /// @return Title of the entry, if exists
324 ///
325 const std::string& Title(void) const { return m_title; }
326 //----------------------------------------------------------------------------
327
328 //============================================================================
329 ///
330 /// @ingroup cpp_kodi_vfs_CDirEntry
331 /// @brief Get the path of the entry
332 ///
333 /// @return File system path of the entry
334 ///
335 const std::string& Path(void) const { return m_path; }
336 //----------------------------------------------------------------------------
337
338 //============================================================================
339 ///
340 /// @ingroup cpp_kodi_vfs_CDirEntry
341 /// @brief Used to check entry is folder
342 ///
343 /// @return true if entry is a folder
344 ///
345 bool IsFolder(void) const { return m_folder; }
346 //----------------------------------------------------------------------------
347
348 //============================================================================
349 ///
350 /// @ingroup cpp_kodi_vfs_CDirEntry
351 /// @brief If file, the size of the file
352 ///
353 /// @return Defined file size
354 ///
355 int64_t Size(void) const { return m_size; }
356 //----------------------------------------------------------------------------
357
358 //============================================================================
359 ///
360 /// @ingroup cpp_kodi_vfs_CDirEntry
361 /// @brief Get file time and date for a new entry
362 ///
363 /// @return The with time_t defined date and time of file
364 ///
365 time_t DateTime() { return m_dateTime; }
366 //----------------------------------------------------------------------------
367
368 //============================================================================
369 ///
370 /// @ingroup cpp_kodi_vfs_CDirEntry
371 /// @brief Set the label name
372 ///
373 /// @param[in] label name of entry
374 ///
375 void SetLabel(const std::string& label) { m_label = label; }
376 //----------------------------------------------------------------------------
377
378 //============================================================================
379 ///
380 /// @ingroup cpp_kodi_vfs_CDirEntry
381 /// @brief Set the title name
382 ///
383 /// @param[in] title title name of entry
384 ///
385 void SetTitle(const std::string& title) { m_title = title; }
386 //----------------------------------------------------------------------------
387
388 //============================================================================
389 ///
390 /// @ingroup cpp_kodi_vfs_CDirEntry
391 /// @brief Set the path of the entry
392 ///
393 /// @param[in] path path of entry
394 ///
395 void SetPath(const std::string& path) { m_path = path; }
396 //----------------------------------------------------------------------------
397
398 //============================================================================
399 ///
400 /// @ingroup cpp_kodi_vfs_CDirEntry
401 /// @brief Set the entry defined as folder
402 ///
403 /// @param[in] folder If true becomes entry defined as folder
404 ///
405 void SetFolder(bool folder) { m_folder = folder; }
406 //----------------------------------------------------------------------------
407
408 //============================================================================
409 ///
410 /// @ingroup cpp_kodi_vfs_CDirEntry
411 /// @brief Set a file size for a new entry
412 ///
413 /// @param[in] size Size to set for dir entry
414 ///
415 void SetSize(int64_t size) { m_size = size; }
416 //----------------------------------------------------------------------------
417
418 //============================================================================
419 ///
420 /// @ingroup cpp_kodi_vfs_CDirEntry
421 /// @brief Set file time and date for a new entry
422 ///
423 /// @param[in] dateTime The with time_t defined date and time of file
424 ///
425 void SetDateTime(time_t dateTime) { m_dateTime = dateTime; }
426 //----------------------------------------------------------------------------
427
428 //============================================================================
429 ///
430 /// @ingroup cpp_kodi_vfs_CDirEntry
431 /// @brief Add a by string defined property entry to directory entry
432 ///
433 /// @note A property can be used to add some special information about a file
434 /// or directory entry, this can be used on other places to do the right work
435 /// of them.
436 ///
437 /// @param[in] id Identification name of property
438 /// @param[in] value The property value to add by given id
439 ///
440 void AddProperty(const std::string& id, const std::string& value) { m_properties[id] = value; }
441 //----------------------------------------------------------------------------
442
443 //============================================================================
444 ///
445 /// @ingroup cpp_kodi_vfs_CDirEntry
446 /// @brief Clear all present properties
447 ///
448 void ClearProperties() { m_properties.clear(); }
449 //----------------------------------------------------------------------------
450
451 //============================================================================
452 ///
453 /// @ingroup cpp_kodi_vfs_CDirEntry
454 /// @brief Get the present properties list on directory entry
455 ///
456 /// @return map with all present properties
457 ///
458 const std::map<std::string, std::string>& GetProperties() const { return m_properties; }
459 //----------------------------------------------------------------------------
460
461 private:
462 std::string m_label;
463 std::string m_title;
464 std::string m_path;
465 std::map<std::string, std::string> m_properties;
466 bool m_folder;
467 int64_t m_size;
468 time_t m_dateTime;
469 };
470 //@}
471 //----------------------------------------------------------------------------
472
473 //============================================================================
474 ///
475 /// @ingroup cpp_kodi_vfs
476 /// @brief Make a directory
477 ///
478 /// The kodi::vfs::CreateDirectory() function shall create a
479 /// new directory with name path.
480 ///
481 /// The newly created directory shall be an empty directory.
482 ///
483 /// @param[in] path Path to the directory.
484 /// @return Upon successful completion, CreateDirectory() shall return true.
485 /// Otherwise false shall be returned, no directory shall be created.
486 ///
487 ///
488 /// -------------------------------------------------------------------------
489 ///
490 /// **Example:**
491 /// ~~~~~~~~~~~~~{.cpp}
492 /// #include <kodi/Filesystem.h>
493 /// ...
494 /// std::string directory = "C:\\my_dir";
495 /// bool ret = kodi::vfs::CreateDirectory(directory);
496 /// fprintf(stderr, "Directory '%s' successfull created: %s\n", directory.c_str(), ret ? "yes" : "no");
497 /// ...
498 /// ~~~~~~~~~~~~~
499 ///
500 inline bool CreateDirectory(const std::string& path)
501 {
502 return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->create_directory(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, path.c_str());
503 }
504 //----------------------------------------------------------------------------
505
506 //============================================================================
507 ///
508 /// @ingroup cpp_kodi_vfs
509 /// @brief Verifying the Existence of a Directory
510 ///
511 /// The kodi::vfs::DirectoryExists() method determines whether
512 /// a specified folder exists.
513 ///
514 /// @param[in] path Path to the directory.
515 /// @return True when it exists, false otherwise.
516 ///
517 ///
518 /// -------------------------------------------------------------------------
519 ///
520 /// **Example:**
521 /// ~~~~~~~~~~~~~{.cpp}
522 /// #include <kodi/Filesystem.h>
523 /// ...
524 /// std::string directory = "C:\\my_dir";
525 /// bool ret = kodi::vfs::DirectoryExists(directory);
526 /// fprintf(stderr, "Directory '%s' present: %s\n", directory.c_str(), ret ? "yes" : "no");
527 /// ...
528 /// ~~~~~~~~~~~~~
529 ///
530 inline bool DirectoryExists(const std::string& path)
531 {
532 return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->directory_exists(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, path.c_str());
533 }
534 //----------------------------------------------------------------------------
535
536 //============================================================================
537 ///
538 /// @ingroup cpp_kodi_vfs
539 /// @brief Removes a directory.
540 ///
541 /// The kodi::vfs::RemoveDirectory() function shall remove a
542 /// directory whose name is given by path.
543 ///
544 /// @param[in] path Path to the directory.
545 /// @return Upon successful completion, the function RemoveDirectory() shall
546 /// return true. Otherwise, false shall be returned, and errno set
547 /// to indicate the error. If false is returned, the named directory
548 /// shall not be changed.
549 ///
550 ///
551 /// -------------------------------------------------------------------------
552 ///
553 /// **Example:**
554 /// ~~~~~~~~~~~~~{.cpp}
555 /// #include <kodi/Filesystem.h>
556 /// ...
557 /// bool ret = kodi::vfs::RemoveDirectory("C:\\my_dir");
558 /// ...
559 /// ~~~~~~~~~~~~~
560 ///
561 inline bool RemoveDirectory(const std::string& path)
562 {
563 return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->remove_directory(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, path.c_str());
564 }
565 //----------------------------------------------------------------------------
566
567 //============================================================================
568 ///
569 /// @ingroup cpp_kodi_vfs
570 /// @brief Lists a directory.
571 ///
572 /// Return the list of files and directories which have been found in the
573 /// specified directory and which respect the given constraint.
574 ///
575 /// It can handle the normal OS dependent paths and also the special virtual
576 /// filesystem from Kodi what starts with \b special://.
577 ///
578 /// @param[in] path The path in which the files and directories are located.
579 /// @param[in] mask Mask to filter out requested files, e.g. "*.avi|*.mpg" to
580 /// files with this ending.
581 /// @param[out] items The returned list directory entries.
582 /// @return True if listing was successful, false otherwise.
583 ///
584 ///
585 /// -------------------------------------------------------------------------
586 ///
587 /// **Example:**
588 /// ~~~~~~~~~~~~~{.cpp}
589 /// #include <kodi/Filesystem.h>
590 ///
591 /// std::vector<kodi::vfs::CDirEntry> items;
592 /// kodi::vfs::GetDirectory("special://temp", "", items);
593 ///
594 /// fprintf(stderr, "Directory have %lu entries\n", items.size());
595 /// for (unsigned long i = 0; i < items.size(); i++)
596 /// {
597 /// fprintf(stderr, " - %04lu -- Folder: %s -- Name: %s -- Path: %s\n",
598 /// i+1,
599 /// items[i].IsFolder() ? "yes" : "no ",
600 /// items[i].Label().c_str(),
601 /// items[i].Path().c_str());
602 /// }
603 /// ~~~~~~~~~~~~~
604 inline bool GetDirectory(const std::string& path, const std::string& mask, std::vector<CDirEntry>& items)
605 {
606 VFSDirEntry* dir_list = nullptr;
607 unsigned int num_items = 0;
608 if (::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_directory(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, path.c_str(), mask.c_str(), &dir_list, &num_items))
609 {
610 if (dir_list)
611 {
612 for (unsigned int i = 0; i < num_items; ++i)
613 items.push_back(CDirEntry(dir_list[i]));
614
615 ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->free_directory(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, dir_list, num_items);
616 }
617
618 return true;
619 }
620 return false;
621 }
622 //----------------------------------------------------------------------------
623
624 //============================================================================
625 ///
626 /// @ingroup cpp_kodi_vfs
627 /// @brief Retrieve MD5sum of a file
628 ///
629 /// @param[in] path path to the file to MD5sum
630 /// @return md5 sum of the file
631 ///
632 ///
633 /// -------------------------------------------------------------------------
634 ///
635 /// **Example:**
636 /// ~~~~~~~~~~~~~{.cpp}
637 /// #include <kodi/Filesystem.h>
638 /// #include <kodi/gui/DialogFileBrowser.h>
639 /// ...
640 /// std::string md5;
641 /// std::string filename;
642 /// if (kodi::gui::DialogFileBrowser::ShowAndGetFile("local", "*.avi|*.mpg|*.mp4",
643 /// "Test File selection to get MD5",
644 /// filename))
645 /// {
646 /// md5 = kodi::vfs::GetFileMD5(filename);
647 /// fprintf(stderr, "MD5 of file '%s' is %s\n", md5.c_str(), filename.c_str());
648 /// }
649 /// ~~~~~~~~~~~~~
650 ///
651 inline std::string GetFileMD5(const std::string& path)
652 {
653 std::string strReturn;
654 char* strMd5 = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_md5(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, path.c_str());
655 if (strMd5 != nullptr)
656 {
657 if (std::strlen(strMd5))
658 strReturn = strMd5;
659 ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, strMd5);
660 }
661 return strReturn;
662 }
663 //----------------------------------------------------------------------------
664
665 //============================================================================
666 ///
667 /// @ingroup cpp_kodi_vfs
668 /// @brief Returns a thumb cache filename
669 ///
670 /// @param[in] filename path to file
671 /// @return cache filename
672 ///
673 ///
674 /// ------------------------------------------------------------------------
675 ///
676 /// **Example:**
677 /// ~~~~~~~~~~~~~{.cpp}
678 /// #include <kodi/Filesystem.h>
679 /// #include <kodi/gui/DialogFileBrowser.h>
680 /// ...
681 /// std::string thumb;
682 /// std::string filename;
683 /// if (kodi::gui::DialogFileBrowser::ShowAndGetFile("local", "*.avi|*.mpg|*.mp4",
684 /// "Test File selection to get Thumnail",
685 /// filename))
686 /// {
687 /// thumb = kodi::vfs::GetCacheThumbName(filename);
688 /// fprintf(stderr, "Thumb name of file '%s' is %s\n", thumb.c_str(), filename.c_str());
689 /// }
690 /// ~~~~~~~~~~~~~
691 ///
692 inline std::string GetCacheThumbName(const std::string& filename)
693 {
694 std::string strReturn;
695 char* strThumbName = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_cache_thumb_name(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str());
696 if (strThumbName != nullptr)
697 {
698 if (std::strlen(strThumbName))
699 strReturn = strThumbName;
700 ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, strThumbName);
701 }
702 return strReturn;
703 }
704 //----------------------------------------------------------------------------
705
706 //============================================================================
707 ///
708 /// @ingroup cpp_kodi_vfs
709 /// @brief Make filename valid
710 ///
711 /// Function to replace not valid characters with '_'. It can be also
712 /// compared with original before in a own loop until it is equal
713 /// (no invalid characters).
714 ///
715 /// @param[in] filename Filename to check and fix
716 /// @return The legal filename
717 ///
718 ///
719 /// ------------------------------------------------------------------------
720 ///
721 /// **Example:**
722 /// ~~~~~~~~~~~~~{.cpp}
723 /// #include <kodi/Filesystem.h>
724 /// ...
725 /// std::string fileName = "///\\jk???lj????.mpg";
726 /// std::string legalName = kodi::vfs::MakeLegalFileName(fileName);
727 /// fprintf(stderr, "Legal name of '%s' is '%s'\n", fileName.c_str(), legalName.c_str());
728 ///
729 /// /* Returns as legal: 'jk___lj____.mpg' */
730 /// ~~~~~~~~~~~~~
731 ///
732 inline std::string MakeLegalFileName(const std::string& filename)
733 {
734 std::string strReturn;
735 char* strLegalFileName = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->make_legal_filename(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str());
736 if (strLegalFileName != nullptr)
737 {
738 if (std::strlen(strLegalFileName))
739 strReturn = strLegalFileName;
740 ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, strLegalFileName);
741 }
742 return strReturn;
743 }
744 //----------------------------------------------------------------------------
745
746 //============================================================================
747 ///
748 /// @ingroup cpp_kodi_vfs
749 /// @brief Make directory name valid
750 ///
751 /// Function to replace not valid characters with '_'. It can be also
752 /// compared with original before in a own loop until it is equal
753 /// (no invalid characters).
754 ///
755 /// @param[in] path Directory name to check and fix
756 /// @return The legal directory name
757 ///
758 ///
759 /// ------------------------------------------------------------------------
760 ///
761 /// **Example:**
762 /// ~~~~~~~~~~~~~{.cpp}
763 /// #include <kodi/Filesystem.h>
764 /// ...
765 /// std::string path = "///\\jk???lj????\\hgjkg";
766 /// std::string legalPath = kodi::vfs::MakeLegalPath(path);
767 /// fprintf(stderr, "Legal name of '%s' is '%s'\n", path.c_str(), legalPath.c_str());
768 ///
769 /// /* Returns as legal: '/jk___lj____/hgjkg' */
770 /// ~~~~~~~~~~~~~
771 ///
772 inline std::string MakeLegalPath(const std::string& path)
773 {
774 std::string strReturn;
775 char* strLegalPath = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->make_legal_path(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, path.c_str());
776 if (strLegalPath != nullptr)
777 {
778 if (std::strlen(strLegalPath))
779 strReturn = strLegalPath;
780 ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, strLegalPath);
781 }
782 return strReturn;
783 }
784 //----------------------------------------------------------------------------
785
786 //============================================================================
787 ///
788 /// \ingroup cpp_kodi
789 /// @brief Returns the translated path
790 ///
791 /// @param[in] source string or unicode - Path to format
792 /// @return A human-readable string suitable for logging
793 ///
794 /// @note Only useful if you are coding for both Linux and Windows.
795 /// e.g. Converts 'special://masterprofile/script_data' -> '/home/user/.kodi/UserData/script_data'
796 /// on Linux.
797 ///
798 ///
799 /// ------------------------------------------------------------------------
800 ///
801 /// **Example:**
802 /// ~~~~~~~~~~~~~{.cpp}
803 /// #include <kodi/Filesystem.h>
804 /// ...
805 /// std::string path = kodi::vfs::TranslateSpecialProtocol("special://masterprofile/script_data");
806 /// fprintf(stderr, "Translated path is: %s\n", path.c_str());
807 /// ...
808 /// ~~~~~~~~~~~~~
809 /// or
810 /// ~~~~~~~~~~~~~{.cpp}
811 /// #include <kodi/Filesystem.h>
812 /// ...
813 /// fprintf(stderr, "Directory 'special://temp' is '%s'\n", kodi::vfs::TranslateSpecialProtocol("special://temp").c_str());
814 /// ...
815 /// ~~~~~~~~~~~~~
816 ///
817 inline std::string TranslateSpecialProtocol(const std::string& source)
818 {
819 std::string strReturn;
820 char* protocol = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->translate_special_protocol(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, source.c_str());
821 if (protocol != nullptr)
822 {
823 if (std::strlen(protocol))
824 strReturn = protocol;
825 ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, protocol);
826 }
827 return strReturn;
828 }
829 //----------------------------------------------------------------------------
830
831 //============================================================================
832 ///
833 /// @ingroup cpp_kodi_vfs
834 /// @brief Return the file name from given complate path string
835 ///
836 /// @param[in] path The complete path include file and directory
837 /// @return Filename from path
838 ///
839 ///
840 /// ------------------------------------------------------------------------
841 ///
842 /// **Example:**
843 /// ~~~~~~~~~~~~~{.cpp}
844 /// #include <kodi/Filesystem.h>
845 /// ...
846 /// std::string fileName = kodi::vfs::GetFileName("special://temp/kodi.log");
847 /// fprintf(stderr, "File name is '%s'\n", fileName.c_str());
848 /// ~~~~~~~~~~~~~
849 ///
850 inline std::string GetFileName(const std::string& path)
851 {
852 /* find the last slash */
853 const size_t slash = path.find_last_of("/\\");
854 return path.substr(slash+1);
855 }
856 //----------------------------------------------------------------------------
857
858 //============================================================================
859 ///
860 /// @ingroup cpp_kodi_vfs
861 /// @brief Return the directory name from given complate path string
862 ///
863 /// @param[in] path The complete path include file and directory
864 /// @return Directory name from path
865 ///
866 ///
867 /// ------------------------------------------------------------------------
868 ///
869 /// **Example:**
870 /// ~~~~~~~~~~~~~{.cpp}
871 /// #include <kodi/Filesystem.h>
872 /// ...
873 /// std::string dirName = kodi::vfs::GetDirectoryName("special://temp/kodi.log");
874 /// fprintf(stderr, "Directory name is '%s'\n", dirName.c_str());
875 /// ~~~~~~~~~~~~~
876 ///
877 inline std::string GetDirectoryName(const std::string& path)
878 {
879 // Will from a full filename return the directory the file resides in.
880 // Keeps the final slash at end and possible |option=foo options.
881
882 size_t iPosSlash = path.find_last_of("/\\");
883 if (iPosSlash == std::string::npos)
884 return ""; // No slash, so no path (ignore any options)
885
886 size_t iPosBar = path.rfind('|');
887 if (iPosBar == std::string::npos)
888 return path.substr(0, iPosSlash + 1); // Only path
889
890 return path.substr(0, iPosSlash + 1) + path.substr(iPosBar); // Path + options
891 }
892 //----------------------------------------------------------------------------
893
894 //============================================================================
895 ///
896 /// @ingroup cpp_kodi_vfs
897 /// @brief Return a size aligned to the chunk size at least as large as the chunk size.
898 ///
899 /// @param[in] chunk The chunk size
900 /// @param[in] minimum The minimum size (or maybe the minimum number of chunks?)
901 /// @return The aligned size
902 ///
903 inline unsigned int GetChunkSize(unsigned int chunk, unsigned int minimum)
904 {
905 if (chunk)
906 return chunk * ((minimum + chunk - 1) / chunk);
907 else
908 return minimum;
909 }
910 //----------------------------------------------------------------------------
911
912 //============================================================================
913 ///
914 /// @ingroup cpp_kodi_vfs
915 /// @brief Check if a file exists.
916 ///
917 /// @param[in] filename The filename to check.
918 /// @param[in] usecache Check in file cache.
919 /// @return true if the file exists false otherwise.
920 ///
921 ///
922 /// -------------------------------------------------------------------------
923 ///
924 /// **Example:**
925 /// ~~~~~~~~~~~~~{.cpp}
926 /// #include <kodi/Filesystem.h>
927 /// ...
928 /// bool exists = kodi::vfs::FileExists("special://temp/kodi.log");
929 /// fprintf(stderr, "Log file should be always present, is it present? %s\n", exists ? "yes" : "no");
930 /// ~~~~~~~~~~~~~
931 ///
932 static inline bool FileExists(const std::string& filename, bool usecache = false)
933 {
934 return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->file_exists(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), usecache);
935 }
936 //----------------------------------------------------------------------------
937
938 //============================================================================
939 ///
940 /// @ingroup cpp_kodi_vfs
941 /// @brief Get file status.
942 ///
943 /// These function return information about a file. Execute (search)
944 /// permission is required on all of the directories in path that
945 /// lead to the file.
946 ///
947 /// The call return a stat structure, which contains the on \ref STAT_STRUCTURE
948 /// defined values.
949 ///
950 /// @warning Not all of the OS file systems implement all of the time fields.
951 ///
952 /// @param[in] filename The filename to read the status from.
953 /// @param[out] buffer The file status is written into this buffer.
954 /// @return On success, tru is returned. On error, fale is returned
955 ///
956 ///
957 /// -------------------------------------------------------------------------
958 ///
959 /// **Example:**
960 /// ~~~~~~~~~~~~~{.cpp}
961 /// #include <kodi/Filesystem.h>
962 /// ...
963 /// STAT_STRUCTURE statFile;
964 /// int ret = kodi::vfs::StatFile("special://temp/kodi.log", &statFile);
965 /// fprintf(stderr, "deviceId (ID of device containing file) = %u\n"
966 /// "size (total size, in bytes) = %lu\n"
967 /// "accessTime (time of last access) = %lu\n"
968 /// "modificationTime (time of last modification) = %lu\n"
969 /// "statusTime (time of last status change) = %lu\n"
970 /// "isDirectory (The stat url is a directory) = %s\n"
971 /// "isSymLink (The stat url is a symbolic link) = %s\n"
972 /// "Return value = %i\n",
973 /// statFile.deviceId,
974 /// statFile.size,
975 /// statFile.accessTime,
976 /// statFile.modificationTime,
977 /// statFile.statusTime,
978 /// statFile.isDirectory ? "true" : "false",
979 /// statFile.isSymLink ? "true" : "false",
980 /// ret);
981 /// ~~~~~~~~~~~~~
982 ///
983 static inline bool StatFile(const std::string& filename, STAT_STRUCTURE& buffer)
984 {
985 struct __stat64 frontendBuffer = { };
986 if (::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->stat_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), &frontendBuffer))
987 {
988 buffer.deviceId = frontendBuffer.st_dev;
989 buffer.size = frontendBuffer.st_size;
990#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD)
991 buffer.accessTime = frontendBuffer.st_atimespec;
992 buffer.modificationTime = frontendBuffer.st_mtimespec;
993 buffer.statusTime = frontendBuffer.st_ctimespec;
994#elif defined(TARGET_WINDOWS)
995 buffer.accessTime = frontendBuffer.st_atime;
996 buffer.modificationTime = frontendBuffer.st_mtime;
997 buffer.statusTime = frontendBuffer.st_ctime;
998#elif defined(TARGET_ANDROID)
999 buffer.accessTime.tv_sec = frontendBuffer.st_atime;
1000 buffer.accessTime.tv_nsec = frontendBuffer.st_atime_nsec;
1001 buffer.modificationTime.tv_sec = frontendBuffer.st_mtime;
1002 buffer.modificationTime.tv_nsec = frontendBuffer.st_mtime_nsec;
1003 buffer.statusTime.tv_sec = frontendBuffer.st_ctime;
1004 buffer.statusTime.tv_nsec = frontendBuffer.st_ctime_nsec;
1005#else
1006 buffer.accessTime = frontendBuffer.st_atim;
1007 buffer.modificationTime = frontendBuffer.st_mtim;
1008 buffer.statusTime = frontendBuffer.st_ctim;
1009#endif
1010 buffer.isDirectory = S_ISDIR(frontendBuffer.st_mode);
1011 buffer.isSymLink = S_ISLNK(frontendBuffer.st_mode);
1012 return true;
1013 }
1014 return false;
1015 }
1016 //----------------------------------------------------------------------------
1017
1018 //============================================================================
1019 ///
1020 /// @ingroup cpp_kodi_vfs
1021 /// @brief Deletes a file.
1022 ///
1023 /// @param[in] filename The filename to delete.
1024 /// @return The file was successfully deleted.
1025 ///
1026 ///
1027 /// -------------------------------------------------------------------------
1028 ///
1029 /// **Example:**
1030 /// ~~~~~~~~~~~~~{.cpp}
1031 /// #include <kodi/Filesystem.h>
1032 /// #include <kodi/gui/DialogFileBrowser.h>
1033 /// #include <kodi/gui/DialogOK.h>
1034 /// ...
1035 /// std::string filename;
1036 /// if (kodi::gui::DialogFileBrowser::ShowAndGetFile("local", "",
1037 /// "Test File selection and delete of them!",
1038 /// filename))
1039 /// {
1040 /// bool successed = kodi::vfs::DeleteFile(filename);
1041 /// if (!successed)
1042 /// kodi::gui::DialogOK::ShowAndGetInput("Error", "Delete of File", filename, "failed!");
1043 /// else
1044 /// kodi::gui::DialogOK::ShowAndGetInput("Information", "Delete of File", filename, "successfull done.");
1045 /// }
1046 /// ~~~~~~~~~~~~~
1047 ///
1048 static inline bool DeleteFile(const std::string& filename)
1049 {
1050 return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->delete_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str());
1051 }
1052 //----------------------------------------------------------------------------
1053
1054 //============================================================================
1055 ///
1056 /// @ingroup cpp_kodi_vfs
1057 /// @brief Rename a file name
1058 ///
1059 /// @param[in] filename The filename to copy.
1060 /// @param[in] newFileName The new filename
1061 /// @return true if successfully renamed
1062 ///
1063 ///
1064 static inline bool RenameFile(const std::string& filename, const std::string& newFileName)
1065 {
1066 return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->rename_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), newFileName.c_str());
1067 }
1068 //----------------------------------------------------------------------------
1069
1070 //============================================================================
1071 ///
1072 /// @ingroup cpp_kodi_vfs
1073 /// @brief Copy a file from source to destination
1074 ///
1075 /// @param[in] filename The filename to copy.
1076 /// @param[in] destination The destination to copy file to
1077 /// @return true if successfully copied
1078 ///
1079 ///
1080 static inline bool CopyFile(const std::string& filename, const std::string& destination)
1081 {
1082 return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->copy_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), destination.c_str());
1083 }
1084 //----------------------------------------------------------------------------
1085
1086 //============================================================================
1087 ///
1088 /// \defgroup cpp_kodi_vfs_CFile class CFile
1089 /// \ingroup cpp_kodi_vfs
1090 ///
1091 /// @brief **Virtual file server control**
1092 ///
1093 /// CFile is the class used for handling Files in Kodi. This class can be used
1094 /// for creating, reading, writing and modifying files. It directly provides unbuffered, binary disk input/output services
1095 ///
1096 /// It has the header \ref Filesystem.h "#include <kodi/Filesystem.h>" be included
1097 /// to enjoy it.
1098 ///
1099 ///
1100 /// ------------------------------------------------------------------------
1101 ///
1102 /// **Example:**
1103 /// ~~~~~~~~~~~~~{.cpp}
1104 /// #include <kodi/Filesystem.h>
1105 ///
1106 /// ...
1107 ///
1108 /// /* Create the needed file handle class */
1109 /// kodi::vfs::CFile myFile();
1110 ///
1111 /// /* In this example we use the user path for the add-on */
1112 /// std::string file = kodi::GetUserPath() + "/myFile.txt";
1113 ///
1114 /// /* Now create and open the file or overwrite if present */
1115 /// myFile.OpenFileForWrite(file, true);
1116 ///
1117 /// const char* str = "I love Kodi!";
1118 ///
1119 /// /* write string */
1120 /// myFile.Write(str, sizeof(str));
1121 ///
1122 /// /* On this way the Close() is not needed to call, becomes done from destructor */
1123 ///
1124 /// ~~~~~~~~~~~~~
1125 ///
1126 //@{
1127 class CFile
1128 {
1129 public:
1130 //==========================================================================
1131 ///
1132 /// @ingroup cpp_kodi_vfs_CFile
1133 /// @brief Construct a new, unopened file
1134 ///
1135 CFile() : m_file(nullptr) { }
1136 //--------------------------------------------------------------------------
1137
1138 //==========================================================================
1139 ///
1140 /// @ingroup cpp_kodi_vfs_CFile
1141 /// @brief Close() is called from the destructor, so explicitly closing the
1142 /// file isn't required
1143 ///
1144 virtual ~CFile() { Close(); }
1145 //--------------------------------------------------------------------------
1146
1147 //==========================================================================
1148 ///
1149 /// @ingroup cpp_kodi_vfs_CFile
1150 /// @brief Open the file with filename via Kodi's \ref cpp_kodi_vfs_CFile
1151 /// "CFile". Needs to be closed by calling Close() when done.
1152 ///
1153 /// @param[in] filename The filename to open.
1154 /// @param[in] flags [opt] The flags to pass, see \ref OpenFileFlags
1155 /// @return True on success or false on failure
1156 ///
1157 bool OpenFile(const std::string& filename, unsigned int flags = 0)
1158 {
1159 Close();
1160 m_file = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->open_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), flags);
1161 return m_file != nullptr;
1162 }
1163 //--------------------------------------------------------------------------
1164
1165 //==========================================================================
1166 ///
1167 /// @ingroup cpp_kodi_vfs_CFile
1168 /// @brief Open the file with filename via Kodi's \ref cpp_kodi_vfs_CFile
1169 /// "CFile" in write mode. Needs to be closed by calling Close() when
1170 /// done.
1171 ///
1172 /// @note Related folders becomes created if not present.
1173 ///
1174 /// @param[in] filename The filename to open.
1175 /// @param[in] overwrite True to overwrite, false otherwise.
1176 /// @return True on success or false on failure
1177 ///
1178 bool OpenFileForWrite(const std::string& filename, bool overwrite = false)
1179 {
1180 Close();
1181
1182 // Try to open the file. If it fails, check if we need to create the directory first
1183 // This way we avoid checking if the directory exists every time
1184 m_file = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->open_file_for_write(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), overwrite);
1185 if (!m_file)
1186 {
1187 std::string cacheDirectory = kodi::vfs::GetDirectoryName(filename);
1188 if (::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->directory_exists(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, cacheDirectory.c_str()) ||
1189 ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->create_directory(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, cacheDirectory.c_str()))
1190 m_file = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->open_file_for_write(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, filename.c_str(), overwrite);
1191 }
1192 return m_file != nullptr;
1193 }
1194 //--------------------------------------------------------------------------
1195
1196 //==========================================================================
1197 ///
1198 /// @ingroup cpp_kodi_vfs_CFile
1199 /// @brief Create a Curl representation
1200 ///
1201 /// @param[in] url the URL of the Type.
1202 /// @return True on success or false on failure
1203 ///
1204 bool CURLCreate(const std::string& url)
1205 {
1206 m_file = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->curl_create(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, url.c_str());
1207 return m_file != nullptr;
1208 }
1209 //--------------------------------------------------------------------------
1210
1211 //==========================================================================
1212 ///
1213 /// @ingroup cpp_kodi_vfs_CFile
1214 /// @brief Add options to the curl file created with CURLCreate
1215 ///
1216 /// @param[in] type option type to set, see \ref CURLOptiontype
1217 /// @param[in] name name of the option
1218 /// @param[in] value value of the option
1219 /// @return True on success or false on failure
1220 ///
1221 bool CURLAddOption(CURLOptiontype type, const std::string& name, const std::string& value)
1222 {
1223 if (!m_file)
1224 {
1225 kodi::Log(ADDON_LOG_ERROR, "kodi::vfs::CURLCreate(...) needed to call before!");
1226 return false;
1227 }
1228 return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->curl_add_option(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file, type, name.c_str(), value.c_str());
1229 }
1230 //--------------------------------------------------------------------------
1231
1232 //==========================================================================
1233 ///
1234 /// @ingroup cpp_kodi_vfs_CFile
1235 /// @brief Open the curl file created with CURLCreate
1236 ///
1237 /// @param[in] flags [opt] The flags to pass, see \ref OpenFileFlags
1238 /// @return True on success or false on failure
1239 ///
1240 bool CURLOpen(unsigned int flags = 0)
1241 {
1242 if (!m_file)
1243 {
1244 kodi::Log(ADDON_LOG_ERROR, "kodi::vfs::CURLCreate(...) needed to call before!");
1245 return false;
1246 }
1247 return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->curl_open(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file, flags);
1248 }
1249 //--------------------------------------------------------------------------
1250
1251 //==========================================================================
1252 ///
1253 /// @ingroup cpp_kodi_vfs_CFile
1254 /// @brief Read from an open file.
1255 ///
1256 /// @param[in] ptr The buffer to store the data in.
1257 /// @param[in] size The size of the buffer.
1258 /// @return number of successfully read bytes if any bytes
1259 /// were read and stored in buffer, zero if no bytes
1260 /// are available to read (end of file was reached)
1261 /// or undetectable error occur, -1 in case of any
1262 /// explicit error
1263 ///
1264 ssize_t Read(void* ptr, size_t size)
1265 {
1266 if (!m_file)
1267 return -1;
1268 return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->read_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file, ptr, size);
1269 }
1270 //--------------------------------------------------------------------------
1271
1272 //==========================================================================
1273 ///
1274 /// @ingroup cpp_kodi_vfs_CFile
1275 /// @brief Read a string from an open file.
1276 ///
1277 /// @param[out] line The buffer to store the data in.
1278 /// @return True when a line was read, false otherwise.
1279 ///
1280 bool ReadLine(std::string &line)
1281 {
1282 line.clear();
1283 if (!m_file)
1284 return false;
1285 // TODO: Read 1024 chars into buffer. If file position advanced that many
1286 // chars, we didn't hit a newline. Otherwise, if file position is 1 or 2
1287 // past the number of bytes read, we read (and skipped) a newline sequence.
1288 char buffer[1025];
1289 if (::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->read_file_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file, buffer, sizeof(buffer)))
1290 {
1291 line = buffer;
1292 return !line.empty();
1293 }
1294 return false;
1295 }
1296 //--------------------------------------------------------------------------
1297
1298 //==========================================================================
1299 ///
1300 /// @ingroup cpp_kodi_vfs_CFile
1301 /// @brief Write to a file opened in write mode.
1302 ///
1303 /// @param[in] ptr Pointer to the data to write, converted to a
1304 /// const void*.
1305 /// @param[in] size Size of the data to write.
1306 /// @return number of successfully written bytes if any
1307 /// bytes were written, zero if no bytes were
1308 /// written and no detectable error occur,-1 in case
1309 /// of any explicit error
1310 ///
1311 ssize_t Write(const void* ptr, size_t size)
1312 {
1313 if (!m_file)
1314 return -1;
1315 return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->write_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file, ptr, size);
1316 }
1317 //--------------------------------------------------------------------------
1318
1319 //==========================================================================
1320 ///
1321 /// @ingroup cpp_kodi_vfs_CFile
1322 /// @brief Flush buffered data.
1323 ///
1324 /// If the given stream was open for writing (or if it was open for updating
1325 /// and the last i/o operation was an output operation) any unwritten data
1326 /// in its output buffer is written to the file.
1327 ///
1328 /// The stream remains open after this call.
1329 ///
1330 /// When a file is closed, either because of a call to close or because the
1331 /// class is destructed, all the buffers associated with it are
1332 /// automatically flushed.
1333 ///
1334 void Flush()
1335 {
1336 if (!m_file)
1337 return;
1338 ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->flush_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file);
1339 }
1340 //--------------------------------------------------------------------------
1341
1342 //==========================================================================
1343 ///
1344 /// @ingroup cpp_kodi_vfs_CFile
1345 /// @brief Set the file's current position.
1346 ///
1347 /// The whence argument is optional and defaults to SEEK_SET (0)
1348 ///
1349 /// @param[in] position the position that you want to seek to
1350 /// @param[in] whence [optional] offset relative to
1351 /// You can set the value of whence to one.
1352 /// of three things:
1353 /// | Value | int | Description |
1354 /// |:--------:|:---:|:----------------------------------------------------|
1355 /// | SEEK_SET | 0 | position is relative to the beginning of the file. This is probably what you had in mind anyway, and is the most commonly used value for whence.
1356 /// | SEEK_CUR | 1 | position is relative to the current file pointer position. So, in effect, you can say, "Move to my current position plus 30 bytes," or, "move to my current position minus 20 bytes."
1357 /// | SEEK_END | 2 | position is relative to the end of the file. Just like SEEK_SET except from the other end of the file. Be sure to use negative values for offset if you want to back up from the end of the file, instead of going past the end into oblivion.
1358 ///
1359 /// @return Returns the resulting offset location as
1360 /// measured in bytes from the beginning of
1361 /// the file. On error, the value -1 is
1362 /// returned.
1363 ///
1364 int64_t Seek(int64_t position, int whence = SEEK_SET)
1365 {
1366 if (!m_file)
1367 return -1;
1368 return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->seek_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file, position, whence);
1369 }
1370 //--------------------------------------------------------------------------
1371
1372 //==========================================================================
1373 ///
1374 /// @ingroup cpp_kodi_vfs_CFile
1375 /// @brief Truncate a file to the requested size.
1376 ///
1377 /// @param[in] size The new max size.
1378 /// @return New size? On error, the value -1 is
1379 /// returned.
1380 ///
1381 int Truncate(int64_t size)
1382 {
1383 if (!m_file)
1384 return -1;
1385 return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->truncate_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file, size);
1386 }
1387 //--------------------------------------------------------------------------
1388
1389 //==========================================================================
1390 ///
1391 /// @ingroup cpp_kodi_vfs_CFile
1392 /// @brief The current offset in an open file.
1393 ///
1394 /// @return The requested offset. On error, the value -1 is
1395 /// returned.
1396 ///
1397 int64_t GetPosition()
1398 {
1399 if (!m_file)
1400 return -1;
1401 return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_position(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file);
1402 }
1403 //--------------------------------------------------------------------------
1404
1405 //==========================================================================
1406 ///
1407 /// @ingroup cpp_kodi_vfs_CFile
1408 /// @brief Get the file size of an open file.
1409 ///
1410 /// @return The requested size. On error, the value -1 is
1411 /// returned.
1412 ///
1413 int64_t GetLength()
1414 {
1415 if (!m_file)
1416 return -1;
1417 return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_length(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file);
1418 }
1419 //--------------------------------------------------------------------------
1420
1421 //==========================================================================
1422 ///
1423 /// @ingroup cpp_kodi_vfs_CFile
1424 /// @brief Checks the file access is on end position.
1425 ///
1426 /// @return If you've reached the end of the file, AtEnd() returns true.
1427 ///
1428 bool AtEnd()
1429 {
1430 if (!m_file)
1431 return true;
1432 int64_t length = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_length(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file);
1433 int64_t position = ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_position(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file);
1434 return position >= length;
1435 }
1436 //--------------------------------------------------------------------------
1437
1438 //==========================================================================
1439 ///
1440 /// @ingroup cpp_kodi_vfs_CFile
1441 /// @brief Close an open file.
1442 ///
1443 void Close()
1444 {
1445 if (!m_file)
1446 return;
1447 ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->close_file(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file);
1448 m_file = nullptr;
1449 }
1450 //--------------------------------------------------------------------------
1451
1452 //==========================================================================
1453 ///
1454 /// @ingroup cpp_kodi_vfs_CFile
1455 /// @brief Get the chunk size for an open file.
1456 ///
1457 /// @return The requested size. On error, the value -1 is
1458 /// returned.
1459 ///
1460 int GetChunkSize()
1461 {
1462 if (!m_file)
1463 return -1;
1464 return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_chunk_size(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file);
1465 }
1466 //--------------------------------------------------------------------------
1467
1468 //==========================================================================
1469 ///
1470 /// @ingroup cpp_kodi_vfs_CFile
1471 /// @brief Get the current download speed of file if loaded from web.
1472 ///
1473 /// @return The current download speed.
1474 ///
1475 double GetFileDownloadSpeed()
1476 {
1477 if (!m_file)
1478 return 0.0;
1479 return ::kodi::addon::CAddonBase::m_interface->toKodi->kodi_filesystem->get_file_download_speed(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, m_file);
1480 }
1481 //--------------------------------------------------------------------------
1482
1483 private:
1484 void* m_file;
1485 };
1486 //@}
1487 //----------------------------------------------------------------------------
1488
1489} /* namespace vfs */
1490} /* namespace kodi */