path.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * Copyright (c) 2012-2014 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/taylor001/crown/blob/master/LICENSE
  4. */
  5. #include "path.h"
  6. #include "platform.h"
  7. #include <ctype.h> // isalpha
  8. namespace crown
  9. {
  10. namespace path
  11. {
  12. bool is_absolute_path(const char* path)
  13. {
  14. CE_ASSERT(path != NULL, "Path must be != NULL");
  15. #if CROWN_PLATFORM_POSIX
  16. return strlen(path) > 0 && path[0] == '/';
  17. #elif CROWN_PLATFORM_WINDOWS
  18. return strlen(path) > 2 && isalpha(path[0]) && path[1] == ':' && path[2] == '\\';
  19. #endif
  20. }
  21. bool is_root_path(const char* path)
  22. {
  23. CE_ASSERT(path != NULL, "Path must be != NULL");
  24. #if CROWN_PLATFORM_POSIX
  25. return is_absolute_path(path) && strlen(path) == 1;
  26. #elif CROWN_PLATFORM_WINDOWS
  27. return is_absolute_path(path) && strlen(path) == 3;
  28. #endif
  29. }
  30. /// Returns the pathname of the path.
  31. /// @note
  32. /// e.g. "/home/project/texture.tga" -> "/home/project"
  33. /// e.g. "/home/project" -> "/home"
  34. /// e.g. "/home" -> "/"
  35. /// e.g. "home" -> ""
  36. ///
  37. /// The @a path must be valid.
  38. void pathname(const char* path, char* str, size_t len)
  39. {
  40. CE_ASSERT(path != NULL, "Path must be != NULL");
  41. CE_ASSERT(str != NULL, "Str must be != NULL");
  42. const char* last_separator = find_last(path, '/');
  43. if (last_separator == end(path))
  44. {
  45. strncpy(str, "", len);
  46. }
  47. else
  48. {
  49. substring(begin(path), last_separator, str, len);
  50. }
  51. }
  52. /// Returns the filename of the path.
  53. /// @note
  54. /// e.g. "/home/project/texture.tga" -> "texture.tga"
  55. /// e.g. "/home/project/texture" -> "texture"
  56. /// e.g. "/home -> "home"
  57. /// e.g. "/" -> ""
  58. ///
  59. /// The @a path must be valid.
  60. void filename(const char* path, char* str, size_t len)
  61. {
  62. CE_ASSERT(path != NULL, "Path must be != NULL");
  63. CE_ASSERT(str != NULL, "Str must be != NULL");
  64. const char* last_separator = find_last(path, '/');
  65. if (last_separator == end(path))
  66. {
  67. strncpy(str, "", len);
  68. }
  69. else
  70. {
  71. substring(last_separator + 1, end(path), str, len);
  72. }
  73. }
  74. /// Returns the basename of the path.
  75. /// @note
  76. /// e.g. "/home/project/texture.tga" -> "texture"
  77. /// e.g. "/home/project" -> "project"
  78. /// e.g. "/" -> ""
  79. ///
  80. /// The @a path must be valid.
  81. void basename(const char* path, char* str, size_t len)
  82. {
  83. CE_ASSERT(path != NULL, "Path must be != NULL");
  84. CE_ASSERT(str != NULL, "Str must be != NULL");
  85. const char* last_separator = find_last(path, '/');
  86. const char* last_dot = find_last(path, '.');
  87. if (last_separator == end(path) && last_dot != end(path))
  88. {
  89. substring(begin(path), last_dot, str, len);
  90. }
  91. else if (last_separator != end(path) && last_dot == end(path))
  92. {
  93. substring(last_separator + 1, end(path), str, len);
  94. }
  95. else if (last_separator == end(path) && last_dot == end(path))
  96. {
  97. strncpy(str, path, len);
  98. }
  99. else
  100. {
  101. substring(last_separator + 1, last_dot, str, len);
  102. }
  103. }
  104. /// Returns the extension of the path.
  105. /// @note
  106. /// e.g. "/home/project/texture.tga" -> "tga"
  107. /// e.g. "/home/project.x/texture" -> ""
  108. ///
  109. /// The @a path must be valid.
  110. void extension(const char* path, char* str, size_t len)
  111. {
  112. CE_ASSERT(path != NULL, "Path must be != NULL");
  113. CE_ASSERT(str != NULL, "Str must be != NULL");
  114. const char* last_dot = find_last(path, '.');
  115. if (last_dot == end(path))
  116. {
  117. strncpy(str, "", len);
  118. }
  119. else
  120. {
  121. substring(last_dot + 1, end(path), str, len);
  122. }
  123. }
  124. /// Returns the filename without the extension.
  125. /// @note
  126. /// e.g. "/home/project/texture.tga" -> "/home/project/texture"
  127. /// e.g. "/home/project/texture" -> "/home/project/texture"
  128. ///
  129. /// The @a path must be valid.
  130. void filename_without_extension(const char* path, char* str, size_t len)
  131. {
  132. CE_ASSERT(path != NULL, "Path must be != NULL");
  133. CE_ASSERT(str != NULL, "Str must be != NULL");
  134. const char* last_dot = find_last(path, '.');
  135. substring(begin(path), last_dot, str, len);
  136. }
  137. /// Fills 'ret' with the same path but without the trailing directory separator.
  138. /// @note
  139. /// e.g. "/home/project/texture.tga/" -> "/home/project/texture.tga"
  140. /// e.g. "/home/project/texture.tga" -> "/home/project/texture.tga"
  141. ///
  142. /// The @a path must be valid.
  143. void strip_trailing_separator(const char* path, char* str, size_t len)
  144. {
  145. CE_ASSERT(path != NULL, "Path must be != NULL");
  146. CE_ASSERT(str != NULL, "Str must be != NULL");
  147. size_t path_len = strlen(path);
  148. if (path[path_len - 1] == '/')
  149. {
  150. substring(begin(path), end(path) - 2, str, len);
  151. }
  152. else
  153. {
  154. substring(begin(path), end(path), str, len);
  155. }
  156. }
  157. } // namespace path
  158. } // namespace crown