Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

327 lines
9.6KB

  1. /* Arduino SdFat Library
  2. * Copyright (C) 2012 by William Greiman
  3. *
  4. * This file is part of the Arduino SdFat Library
  5. *
  6. * This Library is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This Library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with the Arduino SdFat Library. If not, see
  18. * <http://www.gnu.org/licenses/>.
  19. */
  20. #include <SdFat.h>
  21. #include <utility/FmtNumber.h>
  22. //------------------------------------------------------------------------------
  23. /** List directory contents to stdOut.
  24. *
  25. * \param[in] flags The inclusive OR of
  26. *
  27. * LS_DATE - %Print file modification date
  28. *
  29. * LS_SIZE - %Print file size.
  30. *
  31. * LS_R - Recursive list of subdirectories.
  32. */
  33. void SdBaseFile::ls(uint8_t flags) {
  34. ls(SdFat::stdOut(), flags, 0);
  35. }
  36. //------------------------------------------------------------------------------
  37. /** List directory contents.
  38. *
  39. * \param[in] pr Print stream for list.
  40. *
  41. * \param[in] flags The inclusive OR of
  42. *
  43. * LS_DATE - %Print file modification date
  44. *
  45. * LS_SIZE - %Print file size.
  46. *
  47. * LS_R - Recursive list of subdirectories.
  48. *
  49. * \param[in] indent Amount of space before file name. Used for recursive
  50. * list to indicate subdirectory level.
  51. */
  52. //------------------------------------------------------------------------------
  53. void SdBaseFile::ls(Print* pr, uint8_t flags, uint8_t indent) {
  54. if (!isDir()) {
  55. pr->println(F("bad dir"));
  56. return;
  57. }
  58. rewind();
  59. int8_t status;
  60. while ((status = lsPrintNext(pr, flags, indent))) {
  61. if (status > 1 && (flags & LS_R)) {
  62. uint16_t index = curPosition()/32 - 1;
  63. SdBaseFile s;
  64. if (s.open(this, index, O_READ)) s.ls(pr, flags, indent + 2);
  65. seekSet(32 * (index + 1));
  66. }
  67. }
  68. }
  69. //------------------------------------------------------------------------------
  70. // saves 32 bytes on stack for ls recursion
  71. // return 0 - EOF, 1 - normal file, or 2 - directory
  72. int8_t SdBaseFile::lsPrintNext(Print *pr, uint8_t flags, uint8_t indent) {
  73. dir_t dir;
  74. uint8_t w = 0;
  75. while (1) {
  76. if (read(&dir, sizeof(dir)) != sizeof(dir)) return 0;
  77. if (dir.name[0] == DIR_NAME_FREE) return 0;
  78. // skip deleted entry and entries for . and ..
  79. if (dir.name[0] != DIR_NAME_DELETED && dir.name[0] != '.'
  80. && DIR_IS_FILE_OR_SUBDIR(&dir)) break;
  81. }
  82. // indent for dir level
  83. for (uint8_t i = 0; i < indent; i++) pr->write(' ');
  84. // print name
  85. for (uint8_t i = 0; i < 11; i++) {
  86. if (dir.name[i] == ' ')continue;
  87. if (i == 8) {
  88. pr->write('.');
  89. w++;
  90. }
  91. pr->write(dir.name[i]);
  92. w++;
  93. }
  94. if (DIR_IS_SUBDIR(&dir)) {
  95. pr->write('/');
  96. w++;
  97. }
  98. if (flags & (LS_DATE | LS_SIZE)) {
  99. while (w++ < 14) pr->write(' ');
  100. }
  101. // print modify date/time if requested
  102. if (flags & LS_DATE) {
  103. pr->write(' ');
  104. printFatDate(pr, dir.lastWriteDate);
  105. pr->write(' ');
  106. printFatTime(pr, dir.lastWriteTime);
  107. }
  108. // print size if requested
  109. if (!DIR_IS_SUBDIR(&dir) && (flags & LS_SIZE)) {
  110. pr->write(' ');
  111. pr->print(dir.fileSize);
  112. }
  113. pr->println();
  114. return DIR_IS_FILE(&dir) ? 1 : 2;
  115. }
  116. //------------------------------------------------------------------------------
  117. // print uint8_t with width 2
  118. static void print2u(Print* pr, uint8_t v) {
  119. if (v < 10) pr->write('0');
  120. pr->print(v, DEC);
  121. }
  122. //------------------------------------------------------------------------------
  123. /** Print a file's creation date and time
  124. *
  125. * \param[in] pr Print stream for output.
  126. *
  127. * \return The value one, true, is returned for success and
  128. * the value zero, false, is returned for failure.
  129. */
  130. bool SdBaseFile::printCreateDateTime(Print* pr) {
  131. dir_t dir;
  132. if (!dirEntry(&dir)) {
  133. DBG_FAIL_MACRO;
  134. goto fail;
  135. }
  136. printFatDate(pr, dir.creationDate);
  137. pr->write(' ');
  138. printFatTime(pr, dir.creationTime);
  139. return true;
  140. fail:
  141. return false;
  142. }
  143. //------------------------------------------------------------------------------
  144. /** %Print a directory date field to stdOut.
  145. *
  146. * Format is yyyy-mm-dd.
  147. *
  148. * \param[in] fatDate The date field from a directory entry.
  149. */
  150. void SdBaseFile::printFatDate(uint16_t fatDate) {
  151. printFatDate(SdFat::stdOut(), fatDate);
  152. }
  153. //------------------------------------------------------------------------------
  154. /** %Print a directory date field.
  155. *
  156. * Format is yyyy-mm-dd.
  157. *
  158. * \param[in] pr Print stream for output.
  159. * \param[in] fatDate The date field from a directory entry.
  160. */
  161. void SdBaseFile::printFatDate(Print* pr, uint16_t fatDate) {
  162. pr->print(FAT_YEAR(fatDate));
  163. pr->write('-');
  164. print2u(pr, FAT_MONTH(fatDate));
  165. pr->write('-');
  166. print2u(pr, FAT_DAY(fatDate));
  167. }
  168. //------------------------------------------------------------------------------
  169. /** %Print a directory time field to stdOut.
  170. *
  171. * Format is hh:mm:ss.
  172. *
  173. * \param[in] fatTime The time field from a directory entry.
  174. */
  175. void SdBaseFile::printFatTime(uint16_t fatTime) {
  176. printFatTime(SdFat::stdOut(), fatTime);
  177. }
  178. //------------------------------------------------------------------------------
  179. /** %Print a directory time field.
  180. *
  181. * Format is hh:mm:ss.
  182. *
  183. * \param[in] pr Print stream for output.
  184. * \param[in] fatTime The time field from a directory entry.
  185. */
  186. void SdBaseFile::printFatTime(Print* pr, uint16_t fatTime) {
  187. print2u(pr, FAT_HOUR(fatTime));
  188. pr->write(':');
  189. print2u(pr, FAT_MINUTE(fatTime));
  190. pr->write(':');
  191. print2u(pr, FAT_SECOND(fatTime));
  192. }
  193. //------------------------------------------------------------------------------
  194. /** Template for SdBaseFile::printField() */
  195. template <typename Type>
  196. static int printFieldT(SdBaseFile* file, char sign, Type value, char term) {
  197. char buf[3*sizeof(Type) + 3];
  198. char* str = &buf[sizeof(buf)];
  199. if (term) {
  200. *--str = term;
  201. if (term == '\n') {
  202. *--str = '\r';
  203. }
  204. }
  205. #ifdef OLD_FMT
  206. do {
  207. Type m = value;
  208. value /= 10;
  209. *--str = '0' + m - 10*value;
  210. } while (value);
  211. #else // OLD_FMT
  212. str = fmtDec(value, str);
  213. #endif // OLD_FMT
  214. if (sign) {
  215. *--str = sign;
  216. }
  217. return file->write(str, &buf[sizeof(buf)] - str);
  218. }
  219. //------------------------------------------------------------------------------
  220. /** Print a number followed by a field terminator.
  221. * \param[in] value The number to be printed.
  222. * \param[in] term The field terminator. Use '\\n' for CR LF.
  223. * \return The number of bytes written or -1 if an error occurs.
  224. */
  225. int SdBaseFile::printField(uint16_t value, char term) {
  226. return printFieldT(this, 0, value, term);
  227. }
  228. //------------------------------------------------------------------------------
  229. /** Print a number followed by a field terminator.
  230. * \param[in] value The number to be printed.
  231. * \param[in] term The field terminator. Use '\\n' for CR LF.
  232. * \return The number of bytes written or -1 if an error occurs.
  233. */
  234. int SdBaseFile::printField(int16_t value, char term) {
  235. char sign = 0;
  236. if (value < 0) {
  237. sign = '-';
  238. value = -value;
  239. }
  240. return printFieldT(this, sign, (uint16_t)value, term);
  241. }
  242. //------------------------------------------------------------------------------
  243. /** Print a number followed by a field terminator.
  244. * \param[in] value The number to be printed.
  245. * \param[in] term The field terminator. Use '\\n' for CR LF.
  246. * \return The number of bytes written or -1 if an error occurs.
  247. */
  248. int SdBaseFile::printField(uint32_t value, char term) {
  249. return printFieldT(this, 0, value, term);
  250. }
  251. //------------------------------------------------------------------------------
  252. /** Print a number followed by a field terminator.
  253. * \param[in] value The number to be printed.
  254. * \param[in] term The field terminator. Use '\\n' for CR LF.
  255. * \return The number of bytes written or -1 if an error occurs.
  256. */
  257. int SdBaseFile::printField(int32_t value, char term) {
  258. char sign = 0;
  259. if (value < 0) {
  260. sign = '-';
  261. value = -value;
  262. }
  263. return printFieldT(this, sign, (uint32_t)value, term);
  264. }
  265. //------------------------------------------------------------------------------
  266. /** Print a file's modify date and time
  267. *
  268. * \param[in] pr Print stream for output.
  269. *
  270. * \return The value one, true, is returned for success and
  271. * the value zero, false, is returned for failure.
  272. */
  273. bool SdBaseFile::printModifyDateTime(Print* pr) {
  274. dir_t dir;
  275. if (!dirEntry(&dir)) {
  276. DBG_FAIL_MACRO;
  277. goto fail;
  278. }
  279. printFatDate(pr, dir.lastWriteDate);
  280. pr->write(' ');
  281. printFatTime(pr, dir.lastWriteTime);
  282. return true;
  283. fail:
  284. return false;
  285. }
  286. //------------------------------------------------------------------------------
  287. /** Print a file's name
  288. *
  289. * \param[in] pr Print stream for output.
  290. *
  291. * \return The value one, true, is returned for success and
  292. * the value zero, false, is returned for failure.
  293. */
  294. size_t SdBaseFile::printName(Print* pr) {
  295. char name[13];
  296. if (!getFilename(name)) {
  297. DBG_FAIL_MACRO;
  298. goto fail;
  299. }
  300. return pr->print(name);
  301. fail:
  302. return 0;
  303. }
  304. //------------------------------------------------------------------------------
  305. /** Print a file's name to stdOut
  306. *
  307. * \return The value one, true, is returned for success and
  308. * the value zero, false, is returned for failure.
  309. */
  310. size_t SdBaseFile::printName() {
  311. return printName(SdFat::stdOut());
  312. }
  313. //------------------------------------------------------------------------------
  314. size_t SdBaseFile::printFileSize(Print* pr) {
  315. char buf[10];
  316. char *ptr = fmtDec(fileSize(), buf + sizeof(buf));
  317. while (ptr > buf) *--ptr = ' ';
  318. return pr->write(reinterpret_cast<uint8_t *>(buf), sizeof(buf));
  319. }