StdioStream.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. /**
  2. * Copyright (c) 2011-2022 Bill Greiman
  3. * This file is part of the SdFat library for SD memory cards.
  4. *
  5. * MIT License
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a
  8. * copy of this software and associated documentation files (the "Software"),
  9. * to deal in the Software without restriction, including without limitation
  10. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. * and/or sell copies of the Software, and to permit persons to whom the
  12. * Software is furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included
  15. * in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. * DEALINGS IN THE SOFTWARE.
  24. */
  25. #include "StdioStream.h"
  26. #include "../common/FmtNumber.h"
  27. //------------------------------------------------------------------------------
  28. int StdioStream::fclose() {
  29. int rtn = 0;
  30. if (!m_status) {
  31. return EOF;
  32. }
  33. if (m_status & S_SWR) {
  34. if (!flushBuf()) {
  35. rtn = EOF;
  36. }
  37. }
  38. if (!StreamBaseFile::close()) {
  39. rtn = EOF;
  40. }
  41. m_r = 0;
  42. m_w = 0;
  43. m_status = 0;
  44. return rtn;
  45. }
  46. //------------------------------------------------------------------------------
  47. int StdioStream::fflush() {
  48. if ((m_status & (S_SWR | S_SRW)) && !(m_status & S_SRD)) {
  49. if (flushBuf() && StreamBaseFile::sync()) {
  50. return 0;
  51. }
  52. }
  53. return EOF;
  54. }
  55. //------------------------------------------------------------------------------
  56. char* StdioStream::fgets(char* str, size_t num, size_t* len) {
  57. char* s = str;
  58. size_t n;
  59. if (num-- == 0) {
  60. return 0;
  61. }
  62. while (num) {
  63. if ((n = m_r) == 0) {
  64. if (!fillBuf()) {
  65. if (s == str) {
  66. return 0;
  67. }
  68. break;
  69. }
  70. n = m_r;
  71. }
  72. if (n > num) {
  73. n = num;
  74. }
  75. uint8_t* end = reinterpret_cast<uint8_t*>(memchr(m_p, '\n', n));
  76. if (end != 0) {
  77. n = ++end - m_p;
  78. memcpy(s, m_p, n);
  79. m_r -= n;
  80. m_p = end;
  81. s += n;
  82. break;
  83. }
  84. memcpy(s, m_p, n);
  85. m_r -= n;
  86. m_p += n;
  87. s += n;
  88. num -= n;
  89. }
  90. *s = 0;
  91. if (len) {
  92. *len = s - str;
  93. }
  94. return str;
  95. }
  96. //------------------------------------------------------------------------------
  97. bool StdioStream::fopen(const char* path, const char* mode) {
  98. oflag_t oflag;
  99. uint8_t m;
  100. switch (*mode++) {
  101. case 'a':
  102. m = O_WRONLY;
  103. oflag = O_CREAT | O_APPEND;
  104. m_status = S_SWR;
  105. break;
  106. case 'r':
  107. m = O_RDONLY;
  108. oflag = 0;
  109. m_status = S_SRD;
  110. break;
  111. case 'w':
  112. m = O_WRONLY;
  113. oflag = O_CREAT | O_TRUNC;
  114. m_status = S_SWR;
  115. break;
  116. default:
  117. goto fail;
  118. }
  119. while (*mode) {
  120. switch (*mode++) {
  121. case '+':
  122. m_status = S_SRW;
  123. m = O_RDWR;
  124. break;
  125. case 'b':
  126. break;
  127. case 'x':
  128. oflag |= O_EXCL;
  129. break;
  130. default:
  131. goto fail;
  132. }
  133. }
  134. oflag |= m;
  135. if (!StreamBaseFile::open(path, oflag)) {
  136. goto fail;
  137. }
  138. m_r = 0;
  139. m_w = 0;
  140. m_p = m_buf;
  141. return true;
  142. fail:
  143. m_status = 0;
  144. return false;
  145. }
  146. //------------------------------------------------------------------------------
  147. int StdioStream::fputs(const char* str) {
  148. size_t len = strlen(str);
  149. return fwrite(str, 1, len) == len ? len : EOF;
  150. }
  151. //------------------------------------------------------------------------------
  152. size_t StdioStream::fread(void* ptr, size_t size, size_t count) {
  153. uint8_t* dst = reinterpret_cast<uint8_t*>(ptr);
  154. size_t total = size*count;
  155. if (total == 0) {
  156. return 0;
  157. }
  158. size_t need = total;
  159. while (need > m_r) {
  160. memcpy(dst, m_p, m_r);
  161. dst += m_r;
  162. m_p += m_r;
  163. need -= m_r;
  164. if (!fillBuf()) {
  165. return (total - need)/size;
  166. }
  167. }
  168. memcpy(dst, m_p, need);
  169. m_r -= need;
  170. m_p += need;
  171. return count;
  172. }
  173. //------------------------------------------------------------------------------
  174. int StdioStream::fseek(int32_t offset, int origin) {
  175. int32_t pos;
  176. if (m_status & S_SWR) {
  177. if (!flushBuf()) {
  178. goto fail;
  179. }
  180. }
  181. switch (origin) {
  182. case SEEK_CUR:
  183. pos = ftell();
  184. if (pos < 0) {
  185. goto fail;
  186. }
  187. pos += offset;
  188. if (!StreamBaseFile::seekCur(pos)) {
  189. goto fail;
  190. }
  191. break;
  192. case SEEK_SET:
  193. if (!StreamBaseFile::seekSet(offset)) {
  194. goto fail;
  195. }
  196. break;
  197. case SEEK_END:
  198. if (!StreamBaseFile::seekEnd(offset)) {
  199. goto fail;
  200. }
  201. break;
  202. default:
  203. goto fail;
  204. }
  205. m_r = 0;
  206. m_p = m_buf;
  207. return 0;
  208. fail:
  209. return EOF;
  210. }
  211. //------------------------------------------------------------------------------
  212. int32_t StdioStream::ftell() {
  213. uint32_t pos = StreamBaseFile::curPosition();
  214. if (m_status & S_SRD) {
  215. if (m_r > pos) {
  216. return -1L;
  217. }
  218. pos -= m_r;
  219. } else if (m_status & S_SWR) {
  220. pos += m_p - m_buf;
  221. }
  222. return pos;
  223. }
  224. //------------------------------------------------------------------------------
  225. size_t StdioStream::fwrite(const void* ptr, size_t size, size_t count) {
  226. return write(ptr, count*size) < 0 ? EOF : count;
  227. }
  228. //------------------------------------------------------------------------------
  229. int StdioStream::write(const void* buf, size_t count) {
  230. const uint8_t* src = static_cast<const uint8_t*>(buf);
  231. size_t todo = count;
  232. while (todo > m_w) {
  233. memcpy(m_p, src, m_w);
  234. m_p += m_w;
  235. src += m_w;
  236. todo -= m_w;
  237. if (!flushBuf()) {
  238. return EOF;
  239. }
  240. }
  241. memcpy(m_p, src, todo);
  242. m_p += todo;
  243. m_w -= todo;
  244. return count;
  245. }
  246. //------------------------------------------------------------------------------
  247. #if (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
  248. size_t StdioStream::print(const __FlashStringHelper *str) {
  249. const char *p = (const char*)str;
  250. uint8_t c;
  251. while ((c = pgm_read_byte(p))) {
  252. if (putc(c) < 0) {
  253. return 0;
  254. }
  255. p++;
  256. }
  257. return p - (const char*)str;
  258. }
  259. #endif // (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
  260. //------------------------------------------------------------------------------
  261. int StdioStream::printDec(float value, uint8_t prec) {
  262. char buf[24];
  263. char *ptr = fmtDouble(buf + sizeof(buf), value, prec, false);
  264. return write(ptr, buf + sizeof(buf) - ptr);
  265. }
  266. //------------------------------------------------------------------------------
  267. int StdioStream::printDec(signed char n) {
  268. if (n < 0) {
  269. if (fputc('-') < 0) {
  270. return -1;
  271. }
  272. n = -n;
  273. }
  274. return printDec((unsigned char)n);
  275. }
  276. //------------------------------------------------------------------------------
  277. int StdioStream::printDec(int16_t n) {
  278. int s;
  279. uint8_t rtn = 0;
  280. if (n < 0) {
  281. if (fputc('-') < 0) {
  282. return -1;
  283. }
  284. n = -n;
  285. rtn++;
  286. }
  287. if ((s = printDec((uint16_t)n)) < 0) {
  288. return s;
  289. }
  290. return rtn;
  291. }
  292. //------------------------------------------------------------------------------
  293. int StdioStream::printDec(uint16_t n) {
  294. char buf[5];
  295. char *ptr = fmtBase10(buf + sizeof(buf), n);
  296. uint8_t len = buf + sizeof(buf) - ptr;
  297. return write(ptr, len);
  298. }
  299. //------------------------------------------------------------------------------
  300. int StdioStream::printDec(int32_t n) {
  301. uint8_t s = 0;
  302. if (n < 0) {
  303. if (fputc('-') < 0) {
  304. return -1;
  305. }
  306. n = -n;
  307. s = 1;
  308. }
  309. int rtn = printDec((uint32_t)n);
  310. return rtn > 0 ? rtn + s : -1;
  311. }
  312. //------------------------------------------------------------------------------
  313. int StdioStream::printDec(uint32_t n) {
  314. char buf[10];
  315. char *ptr = fmtBase10(buf + sizeof(buf), n);
  316. uint8_t len = buf + sizeof(buf) - ptr;
  317. return write(ptr, len);
  318. }
  319. //------------------------------------------------------------------------------
  320. int StdioStream::printHex(uint32_t n) {
  321. char buf[8];
  322. char *ptr = fmtHex(buf + sizeof(buf), n);
  323. uint8_t len = buf + sizeof(buf) - ptr;
  324. return write(ptr, len);
  325. }
  326. //------------------------------------------------------------------------------
  327. bool StdioStream::rewind() {
  328. if (m_status & S_SWR) {
  329. if (!flushBuf()) {
  330. return false;
  331. }
  332. }
  333. StreamBaseFile::seekSet(0);
  334. m_r = 0;
  335. return true;
  336. }
  337. //------------------------------------------------------------------------------
  338. int StdioStream::ungetc(int c) {
  339. // error if EOF.
  340. if (c == EOF) {
  341. return EOF;
  342. }
  343. // error if not reading.
  344. if ((m_status & S_SRD) == 0) {
  345. return EOF;
  346. }
  347. // error if no space.
  348. if (m_p == m_buf) {
  349. return EOF;
  350. }
  351. m_r++;
  352. m_status &= ~S_EOF;
  353. return *--m_p = (uint8_t)c;
  354. }
  355. //==============================================================================
  356. // private
  357. //------------------------------------------------------------------------------
  358. int StdioStream::fillGet() {
  359. if (!fillBuf()) {
  360. return EOF;
  361. }
  362. m_r--;
  363. return *m_p++;
  364. }
  365. //------------------------------------------------------------------------------
  366. // private
  367. bool StdioStream::fillBuf() {
  368. if (!(m_status &
  369. S_SRD)) { // check for S_ERR and S_EOF ??/////////////////
  370. if (!(m_status & S_SRW)) {
  371. m_status |= S_ERR;
  372. return false;
  373. }
  374. if (m_status & S_SWR) {
  375. if (!flushBuf()) {
  376. return false;
  377. }
  378. m_status &= ~S_SWR;
  379. m_status |= S_SRD;
  380. m_w = 0;
  381. }
  382. }
  383. m_p = m_buf + UNGETC_BUF_SIZE;
  384. int nr = StreamBaseFile::read(m_p, sizeof(m_buf) - UNGETC_BUF_SIZE);
  385. if (nr <= 0) {
  386. m_status |= nr < 0 ? S_ERR : S_EOF;
  387. m_r = 0;
  388. return false;
  389. }
  390. m_r = nr;
  391. return true;
  392. }
  393. //------------------------------------------------------------------------------
  394. // private
  395. bool StdioStream::flushBuf() {
  396. if (!(m_status &
  397. S_SWR)) { // check for S_ERR ??////////////////////////
  398. if (!(m_status & S_SRW)) {
  399. m_status |= S_ERR;
  400. return false;
  401. }
  402. m_status &= ~S_SRD;
  403. m_status |= S_SWR;
  404. m_r = 0;
  405. m_w = sizeof(m_buf);
  406. m_p = m_buf;
  407. return true;
  408. }
  409. uint8_t n = m_p - m_buf;
  410. m_p = m_buf;
  411. m_w = sizeof(m_buf);
  412. if (StreamBaseFile::write(m_buf, n) == n) {
  413. return true;
  414. }
  415. m_status |= S_ERR;
  416. return false;
  417. }
  418. //------------------------------------------------------------------------------
  419. int StdioStream::flushPut(uint8_t c) {
  420. if (!flushBuf()) {
  421. return EOF;
  422. }
  423. m_w--;
  424. return *m_p++ = c;
  425. }
  426. //------------------------------------------------------------------------------
  427. char* StdioStream::fmtSpace(uint8_t len) {
  428. if (m_w < len) {
  429. if (!flushBuf() || m_w < len) {
  430. return 0;
  431. }
  432. }
  433. if (len > m_w) {
  434. return 0;
  435. }
  436. m_p += len;
  437. m_w -= len;
  438. return reinterpret_cast<char*>(m_p);
  439. }