The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

217 lines
6.8KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #include "../jucer_Headers.h"
  19. #include "jucer_CodeHelpers.h"
  20. //==============================================================================
  21. namespace FileHelpers
  22. {
  23. static int64 calculateMemoryHashCode (const void* data, const size_t numBytes)
  24. {
  25. int64 t = 0;
  26. for (size_t i = 0; i < numBytes; ++i)
  27. t = t * 65599 + static_cast <const uint8*> (data)[i];
  28. return t;
  29. }
  30. int64 calculateStreamHashCode (InputStream& in)
  31. {
  32. int64 t = 0;
  33. const int bufferSize = 4096;
  34. HeapBlock <uint8> buffer;
  35. buffer.malloc (bufferSize);
  36. for (;;)
  37. {
  38. const int num = in.read (buffer, bufferSize);
  39. if (num <= 0)
  40. break;
  41. for (int i = 0; i < num; ++i)
  42. t = t * 65599 + buffer[i];
  43. }
  44. return t;
  45. }
  46. int64 calculateFileHashCode (const File& file)
  47. {
  48. ScopedPointer <FileInputStream> stream (file.createInputStream());
  49. return stream != nullptr ? calculateStreamHashCode (*stream) : 0;
  50. }
  51. bool overwriteFileWithNewDataIfDifferent (const File& file, const void* data, size_t numBytes)
  52. {
  53. if (file.getSize() == numBytes
  54. && calculateMemoryHashCode (data, numBytes) == calculateFileHashCode (file))
  55. return true;
  56. if (file.exists())
  57. return file.replaceWithData (data, numBytes);
  58. return file.appendData (data, numBytes);
  59. }
  60. bool overwriteFileWithNewDataIfDifferent (const File& file, const MemoryOutputStream& newData)
  61. {
  62. return overwriteFileWithNewDataIfDifferent (file, newData.getData(), newData.getDataSize());
  63. }
  64. bool overwriteFileWithNewDataIfDifferent (const File& file, const String& newData)
  65. {
  66. const char* const utf8 = newData.toUTF8();
  67. return overwriteFileWithNewDataIfDifferent (file, utf8, strlen (utf8));
  68. }
  69. bool containsAnyNonHiddenFiles (const File& folder)
  70. {
  71. DirectoryIterator di (folder, false);
  72. while (di.next())
  73. if (! di.getFile().isHidden())
  74. return true;
  75. return false;
  76. }
  77. String unixStylePath (const String& path) { return path.replaceCharacter ('\\', '/'); }
  78. String windowsStylePath (const String& path) { return path.replaceCharacter ('/', '\\'); }
  79. String currentOSStylePath (const String& path)
  80. {
  81. #if JUCE_WINDOWS
  82. return windowsStylePath (path);
  83. #else
  84. return unixStylePath (path);
  85. #endif
  86. }
  87. bool isAbsolutePath (const String& path)
  88. {
  89. return File::isAbsolutePath (path)
  90. || path.startsWithChar ('/') // (needed because File::isAbsolutePath will ignore forward-slashes on Windows)
  91. || path.startsWithChar ('$')
  92. || path.startsWithChar ('~')
  93. || (CharacterFunctions::isLetter (path[0]) && path[1] == ':')
  94. || path.startsWithIgnoreCase ("smb:");
  95. }
  96. String appendPath (const String& path, const String& subpath)
  97. {
  98. if (isAbsolutePath (subpath))
  99. return unixStylePath (subpath);
  100. String path1 (unixStylePath (path));
  101. if (! path1.endsWithChar ('/'))
  102. path1 << '/';
  103. return path1 + unixStylePath (subpath);
  104. }
  105. bool shouldPathsBeRelative (String path1, String path2)
  106. {
  107. path1 = unixStylePath (path1);
  108. path2 = unixStylePath (path2);
  109. const int len = jmin (path1.length(), path2.length());
  110. int commonBitLength = 0;
  111. for (int i = 0; i < len; ++i)
  112. {
  113. if (CharacterFunctions::toLowerCase (path1[i]) != CharacterFunctions::toLowerCase (path2[i]))
  114. break;
  115. ++commonBitLength;
  116. }
  117. return path1.substring (0, commonBitLength).removeCharacters ("/:").isNotEmpty();
  118. }
  119. String getRelativePathFrom (const File& file, const File& sourceFolder)
  120. {
  121. #if ! JUCE_WINDOWS
  122. // On a non-windows machine, we can't know if a drive-letter path may be relative or not.
  123. if (CharacterFunctions::isLetter (file.getFullPathName()[0]) && file.getFullPathName()[1] == ':')
  124. return file.getFullPathName();
  125. #endif
  126. return file.getRelativePathFrom (sourceFolder);
  127. }
  128. // removes "/../" bits from the middle of the path
  129. String simplifyPath (String::CharPointerType p)
  130. {
  131. #if JUCE_WINDOWS
  132. if (CharacterFunctions::indexOf (p, CharPointer_ASCII ("/../")) >= 0
  133. || CharacterFunctions::indexOf (p, CharPointer_ASCII ("\\..\\")) >= 0)
  134. #else
  135. if (CharacterFunctions::indexOf (p, CharPointer_ASCII ("/../")) >= 0)
  136. #endif
  137. {
  138. StringArray toks;
  139. #if JUCE_WINDOWS
  140. toks.addTokens (p, "\\/", String::empty);
  141. #else
  142. toks.addTokens (p, "/", String::empty);
  143. #endif
  144. while (toks[0] == ".")
  145. toks.remove (0);
  146. for (int i = 1; i < toks.size(); ++i)
  147. {
  148. if (toks[i] == ".." && toks [i - 1] != "..")
  149. {
  150. toks.removeRange (i - 1, 2);
  151. i = jmax (0, i - 2);
  152. }
  153. }
  154. return toks.joinIntoString ("/");
  155. }
  156. return p;
  157. }
  158. String simplifyPath (const String& path)
  159. {
  160. #if JUCE_WINDOWS
  161. if (path.contains ("\\..\\") || path.contains ("/../"))
  162. #else
  163. if (path.contains ("/../"))
  164. #endif
  165. return simplifyPath (path.getCharPointer());
  166. return path;
  167. }
  168. }