Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

346 rindas
10KB

  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. * \param[in] prec Number of digits after decimal point.
  224. * \return The number of bytes written or -1 if an error occurs.
  225. */
  226. int SdBaseFile::printField(float value, char term, uint8_t prec) {
  227. char buf[24];
  228. char* str = &buf[sizeof(buf)];
  229. if (term) {
  230. *--str = term;
  231. if (term == '\n') {
  232. *--str = '\r';
  233. }
  234. }
  235. str = fmtFloat(value, str, prec);
  236. return write(str, buf + sizeof(buf) - str);
  237. }
  238. //------------------------------------------------------------------------------
  239. /** Print a number followed by a field terminator.
  240. * \param[in] value The number to be printed.
  241. * \param[in] term The field terminator. Use '\\n' for CR LF.
  242. * \return The number of bytes written or -1 if an error occurs.
  243. */
  244. int SdBaseFile::printField(uint16_t value, char term) {
  245. return printFieldT(this, 0, value, term);
  246. }
  247. //------------------------------------------------------------------------------
  248. /** Print a number followed by a field terminator.
  249. * \param[in] value The number to be printed.
  250. * \param[in] term The field terminator. Use '\\n' for CR LF.
  251. * \return The number of bytes written or -1 if an error occurs.
  252. */
  253. int SdBaseFile::printField(int16_t value, char term) {
  254. char sign = 0;
  255. if (value < 0) {
  256. sign = '-';
  257. value = -value;
  258. }
  259. return printFieldT(this, sign, (uint16_t)value, term);
  260. }
  261. //------------------------------------------------------------------------------
  262. /** Print a number followed by a field terminator.
  263. * \param[in] value The number to be printed.
  264. * \param[in] term The field terminator. Use '\\n' for CR LF.
  265. * \return The number of bytes written or -1 if an error occurs.
  266. */
  267. int SdBaseFile::printField(uint32_t value, char term) {
  268. return printFieldT(this, 0, value, term);
  269. }
  270. //------------------------------------------------------------------------------
  271. /** Print a number followed by a field terminator.
  272. * \param[in] value The number to be printed.
  273. * \param[in] term The field terminator. Use '\\n' for CR LF.
  274. * \return The number of bytes written or -1 if an error occurs.
  275. */
  276. int SdBaseFile::printField(int32_t value, char term) {
  277. char sign = 0;
  278. if (value < 0) {
  279. sign = '-';
  280. value = -value;
  281. }
  282. return printFieldT(this, sign, (uint32_t)value, term);
  283. }
  284. //------------------------------------------------------------------------------
  285. /** Print a file's modify date and time
  286. *
  287. * \param[in] pr Print stream for output.
  288. *
  289. * \return The value one, true, is returned for success and
  290. * the value zero, false, is returned for failure.
  291. */
  292. bool SdBaseFile::printModifyDateTime(Print* pr) {
  293. dir_t dir;
  294. if (!dirEntry(&dir)) {
  295. DBG_FAIL_MACRO;
  296. goto fail;
  297. }
  298. printFatDate(pr, dir.lastWriteDate);
  299. pr->write(' ');
  300. printFatTime(pr, dir.lastWriteTime);
  301. return true;
  302. fail:
  303. return false;
  304. }
  305. //------------------------------------------------------------------------------
  306. /** Print a file's name
  307. *
  308. * \param[in] pr Print stream for output.
  309. *
  310. * \return The value one, true, is returned for success and
  311. * the value zero, false, is returned for failure.
  312. */
  313. size_t SdBaseFile::printName(Print* pr) {
  314. char name[13];
  315. if (!getFilename(name)) {
  316. DBG_FAIL_MACRO;
  317. goto fail;
  318. }
  319. return pr->print(name);
  320. fail:
  321. return 0;
  322. }
  323. //------------------------------------------------------------------------------
  324. /** Print a file's name to stdOut
  325. *
  326. * \return The value one, true, is returned for success and
  327. * the value zero, false, is returned for failure.
  328. */
  329. size_t SdBaseFile::printName() {
  330. return printName(SdFat::stdOut());
  331. }
  332. //------------------------------------------------------------------------------
  333. size_t SdBaseFile::printFileSize(Print* pr) {
  334. char buf[10];
  335. char *ptr = fmtDec(fileSize(), buf + sizeof(buf));
  336. while (ptr > buf) *--ptr = ' ';
  337. return pr->write(reinterpret_cast<uint8_t *>(buf), sizeof(buf));
  338. }