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.

194 lines
6.0KB

  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. int64 calculateStreamHashCode (InputStream& in)
  24. {
  25. int64 t = 0;
  26. const int bufferSize = 4096;
  27. HeapBlock <uint8> buffer;
  28. buffer.malloc (bufferSize);
  29. for (;;)
  30. {
  31. const int num = in.read (buffer, bufferSize);
  32. if (num <= 0)
  33. break;
  34. for (int i = 0; i < num; ++i)
  35. t = t * 65599 + buffer[i];
  36. }
  37. return t;
  38. }
  39. int64 calculateFileHashCode (const File& file)
  40. {
  41. ScopedPointer <FileInputStream> stream (file.createInputStream());
  42. return stream != nullptr ? calculateStreamHashCode (*stream) : 0;
  43. }
  44. bool overwriteFileWithNewDataIfDifferent (const File& file, const void* data, int numBytes)
  45. {
  46. if (file.getSize() == numBytes)
  47. {
  48. MemoryInputStream newStream (data, numBytes, false);
  49. if (calculateStreamHashCode (newStream) == calculateFileHashCode (file))
  50. return true;
  51. }
  52. TemporaryFile temp (file);
  53. return temp.getFile().appendData (data, numBytes)
  54. && temp.overwriteTargetFileWithTemporary();
  55. }
  56. bool overwriteFileWithNewDataIfDifferent (const File& file, const MemoryOutputStream& newData)
  57. {
  58. return overwriteFileWithNewDataIfDifferent (file, newData.getData(), newData.getDataSize());
  59. }
  60. bool overwriteFileWithNewDataIfDifferent (const File& file, const String& newData)
  61. {
  62. const char* const utf8 = newData.toUTF8();
  63. return overwriteFileWithNewDataIfDifferent (file, utf8, strlen (utf8));
  64. }
  65. bool containsAnyNonHiddenFiles (const File& folder)
  66. {
  67. DirectoryIterator di (folder, false);
  68. while (di.next())
  69. if (! di.getFile().isHidden())
  70. return true;
  71. return false;
  72. }
  73. String unixStylePath (const String& path)
  74. {
  75. return path.replaceCharacter ('\\', '/');
  76. }
  77. String windowsStylePath (const String& path)
  78. {
  79. return path.replaceCharacter ('/', '\\');
  80. }
  81. String appendPath (const String& path, const String& subpath)
  82. {
  83. if (File::isAbsolutePath (subpath)
  84. || subpath.startsWithChar ('$')
  85. || subpath.startsWithChar ('~')
  86. || (CharacterFunctions::isLetter (subpath[0]) && subpath[1] == ':'))
  87. return subpath.replaceCharacter ('\\', '/');
  88. String path1 (path.replaceCharacter ('\\', '/'));
  89. if (! path1.endsWithChar ('/'))
  90. path1 << '/';
  91. return path1 + subpath.replaceCharacter ('\\', '/');
  92. }
  93. bool shouldPathsBeRelative (String path1, String path2)
  94. {
  95. path1 = unixStylePath (path1);
  96. path2 = unixStylePath (path2);
  97. const int len = jmin (path1.length(), path2.length());
  98. int commonBitLength = 0;
  99. for (int i = 0; i < len; ++i)
  100. {
  101. if (CharacterFunctions::toLowerCase (path1[i]) != CharacterFunctions::toLowerCase (path2[i]))
  102. break;
  103. ++commonBitLength;
  104. }
  105. return path1.substring (0, commonBitLength).removeCharacters ("/:").isNotEmpty();
  106. }
  107. //==============================================================================
  108. bool isJuceFolder (const File& folder)
  109. {
  110. return folder.getFileName().containsIgnoreCase ("juce")
  111. && folder.getChildFile ("juce.h").exists()
  112. && folder.getChildFile ("modules").exists();
  113. }
  114. static File lookInFolderForJuceFolder (const File& folder)
  115. {
  116. for (DirectoryIterator di (folder, false, "*juce*", File::findDirectories); di.next();)
  117. {
  118. if (isJuceFolder (di.getFile()))
  119. return di.getFile();
  120. }
  121. return File::nonexistent;
  122. }
  123. File findParentJuceFolder (const File& file)
  124. {
  125. File f (file);
  126. while (f.exists() && f.getParentDirectory() != f)
  127. {
  128. if (isJuceFolder (f))
  129. return f;
  130. File found = lookInFolderForJuceFolder (f);
  131. if (found.exists())
  132. return found;
  133. f = f.getParentDirectory();
  134. }
  135. return File::nonexistent;
  136. }
  137. File findDefaultJuceFolder()
  138. {
  139. File f = findParentJuceFolder (File::getSpecialLocation (File::currentApplicationFile));
  140. if (! f.exists())
  141. f = lookInFolderForJuceFolder (File::getSpecialLocation (File::userHomeDirectory));
  142. if (! f.exists())
  143. f = lookInFolderForJuceFolder (File::getSpecialLocation (File::userDocumentsDirectory));
  144. return f;
  145. }
  146. }