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.

167 lines
5.4KB

  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 int numBytes)
  24. {
  25. int64 t = 0;
  26. for (int 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, int 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. else
  59. return file.appendData (data, numBytes);
  60. }
  61. bool overwriteFileWithNewDataIfDifferent (const File& file, const MemoryOutputStream& newData)
  62. {
  63. return overwriteFileWithNewDataIfDifferent (file, newData.getData(), newData.getDataSize());
  64. }
  65. bool overwriteFileWithNewDataIfDifferent (const File& file, const String& newData)
  66. {
  67. const char* const utf8 = newData.toUTF8();
  68. return overwriteFileWithNewDataIfDifferent (file, utf8, strlen (utf8));
  69. }
  70. bool containsAnyNonHiddenFiles (const File& folder)
  71. {
  72. DirectoryIterator di (folder, false);
  73. while (di.next())
  74. if (! di.getFile().isHidden())
  75. return true;
  76. return false;
  77. }
  78. String unixStylePath (const String& path)
  79. {
  80. return path.replaceCharacter ('\\', '/');
  81. }
  82. String windowsStylePath (const String& path)
  83. {
  84. return path.replaceCharacter ('/', '\\');
  85. }
  86. bool isAbsolutePath (const String& path)
  87. {
  88. return File::isAbsolutePath (path)
  89. || path.startsWithChar ('/') // (needed because File::isAbsolutePath will ignore forward-slashes on Windows)
  90. || path.startsWithChar ('$')
  91. || path.startsWithChar ('~')
  92. || (CharacterFunctions::isLetter (path[0]) && path[1] == ':')
  93. || path.startsWithIgnoreCase ("smb:");
  94. }
  95. static String appendPath (const String& path, const String& subpath)
  96. {
  97. if (isAbsolutePath (subpath))
  98. return subpath.replaceCharacter ('\\', '/');
  99. String path1 (path.replaceCharacter ('\\', '/'));
  100. if (! path1.endsWithChar ('/'))
  101. path1 << '/';
  102. return path1 + subpath.replaceCharacter ('\\', '/');
  103. }
  104. bool shouldPathsBeRelative (String path1, String path2)
  105. {
  106. path1 = unixStylePath (path1);
  107. path2 = unixStylePath (path2);
  108. const int len = jmin (path1.length(), path2.length());
  109. int commonBitLength = 0;
  110. for (int i = 0; i < len; ++i)
  111. {
  112. if (CharacterFunctions::toLowerCase (path1[i]) != CharacterFunctions::toLowerCase (path2[i]))
  113. break;
  114. ++commonBitLength;
  115. }
  116. return path1.substring (0, commonBitLength).removeCharacters ("/:").isNotEmpty();
  117. }
  118. String getRelativePathFrom (const File& file, const File& sourceFolder)
  119. {
  120. #if ! JUCE_WINDOWS
  121. // On a non-windows machine, we can't know if a drive-letter path may be relative or not.
  122. if (CharacterFunctions::isLetter (file.getFullPathName()[0]) && file.getFullPathName()[1] == ':')
  123. return file.getFullPathName();
  124. #endif
  125. return file.getRelativePathFrom (sourceFolder);
  126. }
  127. }