Collection of DPF-based plugins for packaging
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

107 lines
3.4KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2025 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any purpose with
  6. * or without fee is hereby granted, provided that the above copyright notice and this
  7. * permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  10. * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  11. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  12. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  13. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #ifndef DISTRHO_FILESYSTEM_UTILS_HPP_INCLUDED
  17. #define DISTRHO_FILESYSTEM_UTILS_HPP_INCLUDED
  18. #include "String.hpp"
  19. #include <cstdio>
  20. #ifdef DISTRHO_OS_WINDOWS
  21. # include <stringapiset.h>
  22. #endif
  23. START_NAMESPACE_DISTRHO
  24. // --------------------------------------------------------------------------------------------------------------------
  25. // filesystem related calls
  26. /*
  27. * Wrapper around `fopen` call, needed on Windows because its C standard functions use ASCII instead of UTF-8.
  28. */
  29. static inline
  30. FILE* d_fopen(const char* const pathname, const char* const mode)
  31. {
  32. #ifdef DISTRHO_OS_WINDOWS
  33. WCHAR lpathname[MAX_PATH];
  34. WCHAR lmode[4];
  35. if (MultiByteToWideChar(CP_UTF8, 0, pathname, -1, lpathname, ARRAY_SIZE(lpathname)) != 0 &&
  36. MultiByteToWideChar(CP_UTF8, 0, mode, -1, lmode, ARRAY_SIZE(lmode)) != 0)
  37. return _wfopen(lpathname, lmode);
  38. #endif
  39. return fopen(pathname, mode);
  40. }
  41. // --------------------------------------------------------------------------------------------------------------------
  42. // filesystem related classes
  43. /**
  44. Handy class to help write files in a safe way, which does:
  45. - open pathname + ".tmp" instead of opening a file directly (so partial writes are safe)
  46. - on close, flush data to disk and rename file to remove ".tmp"
  47. To use it, create a local variable (on the stack) and call ok() or manually check @a fd variable.
  48. @code
  49. if (const SafeFileWriter file("/path/to/file.txt"); file.ok())
  50. file.write("Success!");
  51. @endcode
  52. */
  53. struct SafeFileWriter
  54. {
  55. String filename;
  56. FILE* const fd;
  57. /**
  58. Constructor, opening @a pathname + ".tmp" for writing.
  59. */
  60. SafeFileWriter(const char* const pathname, const char* const mode = "w")
  61. : filename(pathname),
  62. fd(d_fopen(filename + ".tmp", mode)) {}
  63. /**
  64. Destructor, will flush file data contents, close and rename file.
  65. */
  66. ~SafeFileWriter()
  67. {
  68. if (fd == nullptr)
  69. return;
  70. std::fflush(fd);
  71. std::fclose(fd);
  72. std::rename(filename + ".tmp", filename);
  73. }
  74. /** Check if the file was opened successfully. */
  75. inline bool ok() const noexcept
  76. {
  77. return fd != nullptr;
  78. }
  79. /** Wrapper around `fwrite`, purely for convenience. */
  80. inline size_t write(const void* const ptr, const size_t size, const size_t nmemb = 1) const
  81. {
  82. return std::fwrite(ptr, size, nmemb, fd);
  83. }
  84. };
  85. // --------------------------------------------------------------------------------------------------------------------
  86. END_NAMESPACE_DISTRHO
  87. #endif // DISTRHO_FILESYSTEM_UTILS_HPP_INCLUDED