PageRenderTime 24ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/kernel/stream.c

https://github.com/tcr/jiauliyan-os
C | 860 lines | 680 code | 132 blank | 48 comment | 153 complexity | f197744e98f2b2f584f4896f90e5ae77 MD5 | raw file
  1. /*
  2. * Jiauliyan OS - Released under the MIT License
  3. * Copyright (C) 2011 Paul Booth, Jialiya Huang, Tim Ryan
  4. * https://github.com/timcameronryan/jiauliyan
  5. *
  6. * Based on work by Nick Johnson's Rhombus OS, under the OpenBSD license
  7. * Copyright (C) 2009, 2010 Nick Johnson <nickbjohnson4224 at gmail.com>
  8. * https://github.com/nickbjohnson4224/rhombus/
  9. */
  10. #include <stream.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <stdarg.h>
  14. #include <stdint.h>
  15. #include <ctype.h>
  16. #include <errno.h>
  17. #include <math.h>
  18. #include <common.h>
  19. #include <vga.h>
  20. /*
  21. * stream initializer
  22. */
  23. stream_s *stream_create(
  24. int (*get)(stream_s *stream),
  25. int (*put)(stream_s *stream, unsigned char s),
  26. long int (*avail)(struct __stream *stream),
  27. int (*seek)(stream_s *stream, long pos, int whence),
  28. void *data)
  29. {
  30. stream_s *s = (stream_s *) malloc(sizeof(stream_s));
  31. s->get = get;
  32. s->put = put;
  33. s->avail = avail;
  34. s->seek = seek;
  35. s->data = data;
  36. s->ferr = 0;
  37. return s;
  38. }
  39. void stream_destroy(stream_s *stream)
  40. {
  41. free(stream);
  42. }
  43. /* stream impl dummies */
  44. int stream_no_get(stream_s *stream)
  45. {
  46. (void) stream;
  47. return EOF;
  48. }
  49. int stream_no_put(stream_s *stream, unsigned char s)
  50. {
  51. (void) stream; (void) s;
  52. return EOF;
  53. }
  54. long int stream_no_avail(stream_s *stream)
  55. {
  56. (void) stream;
  57. return 0;
  58. }
  59. int stream_no_seek(stream_s *stream, long pos, int whence)
  60. {
  61. (void) stream; (void) pos; (void) whence;
  62. return -1;
  63. }
  64. /*
  65. * stream utilities
  66. */
  67. size_t stream_write(stream_s *stream, const void *ptr, size_t size)
  68. {
  69. unsigned char *p = (unsigned char *) ptr;
  70. size_t i;
  71. for (i = 0; i < size; i++) {
  72. if (stream->put(stream, *p) == EOF)
  73. break;
  74. p++;
  75. }
  76. return i;
  77. }
  78. /*
  79. * byte stream
  80. */
  81. typedef struct {
  82. unsigned char *buf;
  83. long int size;
  84. long int capacity;
  85. long int pos;
  86. } bytestream_s;
  87. /* bytestream impl */
  88. static int bytestream_get(stream_s *stream)
  89. {
  90. bytestream_s *data = (bytestream_s *) stream->data;
  91. if (data->pos >= data->size)
  92. return EOF;
  93. return data->buf[data->pos++];
  94. }
  95. static int bytestream_put(stream_s *stream, unsigned char c)
  96. {
  97. bytestream_s *data = (bytestream_s *) stream->data;
  98. // expand file size
  99. if (data->pos >= data->capacity) {
  100. data->capacity += BUFSIZ;
  101. data->buf = (unsigned char *) realloc(data->buf, data->capacity);
  102. }
  103. if (data->pos + 1 > data->size)
  104. data->size = data->pos + 1;
  105. data->buf[data->pos++] = c;
  106. return (int) c;
  107. }
  108. static int bytestream_seek(stream_s *stream, long pos, int origin)
  109. {
  110. UNUSED(origin);
  111. bytestream_s *data = (bytestream_s *) stream->data;
  112. data->pos = pos;
  113. return 0;
  114. }
  115. /* bytestream api */
  116. stream_s *bytestream_create(long int capacity)
  117. {
  118. bytestream_s *data = malloc(sizeof(bytestream_s));
  119. data->buf = (unsigned char *) malloc(capacity);
  120. data->size = 0;
  121. data->capacity = capacity;
  122. data->pos = 0;
  123. stream_s *stream = malloc(sizeof(stream_s));
  124. stream->get = bytestream_get;
  125. stream->put = bytestream_put;
  126. stream->seek = bytestream_seek;
  127. stream->data = data;
  128. return stream;
  129. }
  130. void bytestream_destroy(stream_s *stream)
  131. {
  132. free(stream->data);
  133. free(stream);
  134. }
  135. long int bytestream_size(stream_s *stream)
  136. {
  137. bytestream_s *data = (bytestream_s *) stream->data;
  138. return data->size;
  139. }
  140. unsigned char *bytestream_data(stream_s *stream)
  141. {
  142. bytestream_s *data = (bytestream_s *) stream->data;
  143. return data->buf;
  144. }
  145. /*
  146. * string formatting
  147. */
  148. #define TYPE_STRING 0 // String
  149. #define TYPE_CHAR 1 // Character
  150. #define TYPE_LITERAL 2 // Literal '%"
  151. #define TYPE_INT 3 // Signed integer
  152. #define TYPE_UINT 4 // Unsigned integer
  153. #define TYPE_DOUBLE 5 // Floating point
  154. size_t stream_putbyte(stream_s *stream, unsigned char b)
  155. {
  156. stream->put(stream, b);
  157. return 1;
  158. }
  159. size_t stream_putchar(stream_s *stream, char c)
  160. {
  161. stream->put(stream, (unsigned char) c);
  162. return 1;
  163. }
  164. size_t stream_putstring(stream_s *stream, const char *text)
  165. {
  166. if (text == NULL)
  167. text = "(null)";
  168. size_t i;
  169. for (i = 0; i < strlen(text); i++)
  170. stream_putchar(stream, text[i]);
  171. return i;
  172. }
  173. size_t stream_putuint(stream_s *stream, unsigned int value, int flags)
  174. {
  175. /* shortcut */
  176. if (value == 0) {
  177. return stream_putchar(stream, '0');
  178. }
  179. const char *digits_lower = "0123456789abcdef";
  180. const char *digits_upper = "0123456789ABCDEF";
  181. const char *digits = flags & FLAG_UPPER ? digits_upper : digits_lower;
  182. int base = 10;
  183. if (flags & FLAG_OCTAL) base = 8;
  184. else if (flags & FLAG_HEX) base = 16;
  185. int len = 0;
  186. /* prefixes */
  187. if (flags & FLAG_SIGN) {
  188. stream_putchar(stream, '+');
  189. len++;
  190. }
  191. if (flags & FLAG_ALT) {
  192. if (flags & FLAG_OCTAL) {
  193. stream_putchar(stream, '0');
  194. len++;
  195. }
  196. if (flags & FLAG_HEX) {
  197. stream_putstring(stream, (flags & FLAG_UPPER) ? "0X" : "0x");
  198. len += 2;
  199. }
  200. }
  201. /* print digits top down */
  202. int i, divisor = 1;
  203. for (i = 0; i < 16; i++) {
  204. if (divisor * base > (int) value)
  205. break;
  206. divisor *= base;
  207. }
  208. for ( ; i >= 0; i--, len++) {
  209. stream_putchar(stream, digits[(int) (value / divisor) % base]);
  210. divisor /= base;
  211. }
  212. return len;
  213. }
  214. size_t stream_putint(stream_s *stream, int value, int flags)
  215. {
  216. size_t len;
  217. if (value < 0) {
  218. stream_putchar(stream, '-');
  219. len = stream_putuint(stream, -value, flags) + 1;
  220. } else {
  221. len = stream_putuint(stream, value, flags);
  222. }
  223. return len;
  224. }
  225. /**********************************************************************/
  226. /** double formatting code */
  227. /** TODO: revise this to be smaller */
  228. /**********************************************************************/
  229. char *strdup(const char *string)
  230. {
  231. char *nstr;
  232. nstr = (char *) malloc(strlen(string) + 1);
  233. if (nstr)
  234. strcpy(nstr, string);
  235. return nstr;
  236. }
  237. char *strvcat(const char *s1, ...) {
  238. va_list ap;
  239. const char *argv[16];
  240. char *fullstring;
  241. size_t i, length, pos;
  242. va_start(ap, s1);
  243. argv[0] = s1;
  244. for (i = 1; i < 16; i++) {
  245. argv[i] = va_arg(ap, const char*);
  246. if (!argv[i]) {
  247. break;
  248. }
  249. }
  250. for (length = 0, i = 0; i < 16 && argv[i]; i++) {
  251. length += strlen(argv[i]);
  252. }
  253. fullstring = malloc(length + 1);
  254. if (!fullstring) {
  255. errno = ENOMEM;
  256. return NULL;
  257. }
  258. fullstring[0] = '\0';
  259. for (i = 0, pos = 0; i < 16 && argv[i]; i++) {
  260. strcat(&fullstring[pos], argv[i]);
  261. pos += strlen(argv[i]);
  262. }
  263. return fullstring;
  264. }
  265. long double logl(long double x) {
  266. return __builtin_logl(x);
  267. }
  268. long double log10l(long double x)
  269. {
  270. return (logl(x) / M_LN10);
  271. }
  272. long double expl(long double x)
  273. {
  274. return __builtin_expl(x);
  275. }
  276. long double powl(long double b, long double e) {
  277. return expl(e * logl(b));
  278. }
  279. long double modfl(long double x, long double *iptr)
  280. {
  281. if (fabs(x) >= 4503599627370496.0) {
  282. *iptr = x;
  283. return 0.0;
  284. }
  285. else if (fabs(x) < 1.0) {
  286. *iptr = 0.0;
  287. return x;
  288. }
  289. else {
  290. *iptr = (long double) (int64_t) x;
  291. return (x - *iptr);
  292. }
  293. }
  294. long double floorl(long double x)
  295. {
  296. modfl(x, &x);
  297. if (x < 0.0) x -= 1.0;
  298. return x;
  299. }
  300. size_t strlcpy(char *dst, const char *src, size_t siz) {
  301. char *d = dst;
  302. const char *s = src;
  303. size_t n = siz;
  304. /* Copy as many bytes as will fit */
  305. if (n != 0) {
  306. while (--n != 0) {
  307. if ((*d++ = *s++) == '\0') {
  308. break;
  309. }
  310. }
  311. }
  312. /* Not enough room in dst, add NUL and traverse rest of src */
  313. if (n == 0) {
  314. if (siz != 0) {
  315. *d = '\0'; /* NUL-terminate dst */
  316. }
  317. while (*s++);
  318. }
  319. return (s - src - 1); /* count does not include NUL */
  320. }
  321. size_t strlcat(char *dst, const char *src, size_t siz) {
  322. char *d = dst;
  323. const char *s = src;
  324. size_t n = siz;
  325. size_t dlen;
  326. /* Find the end of dst and adjust bytes left but don't go past end */
  327. while (n-- != 0 && *d != '\0') {
  328. d++;
  329. }
  330. dlen = d - dst;
  331. n = siz - dlen;
  332. if (n == 0) {
  333. return (dlen + strlen(s));
  334. }
  335. while (*s != '\0') {
  336. if (n != 1) {
  337. *d++ = *s;
  338. n--;
  339. }
  340. s++;
  341. }
  342. *d = '\0';
  343. return (dlen + (s - src)); /* count does not include NUL */
  344. }
  345. static char *__format_uint(unsigned int value, int flags) {
  346. char buffer[16];
  347. int i;
  348. int base;
  349. const char *digits_lower = "0123456789abcdef";
  350. const char *digits_upper = "0123456789ABCDEF";
  351. const char *digits;
  352. if (flags & FLAG_OCTAL) base = 8;
  353. else if (flags & FLAG_HEX) base = 16;
  354. else base = 10;
  355. if (value == 0) {
  356. return strdup("0");
  357. }
  358. if (flags & FLAG_UPPER) {
  359. digits = digits_upper;
  360. }
  361. else {
  362. digits = digits_lower;
  363. }
  364. buffer[15] = '\0';
  365. for (i = 14; i >= 0; i--) {
  366. if (!value) break;
  367. buffer[i] = digits[value % base];
  368. value /= base;
  369. }
  370. if (flags & FLAG_SIGN) {
  371. buffer[i--] = '+';
  372. }
  373. i++;
  374. if (flags & FLAG_ALT) {
  375. if (flags & FLAG_OCTAL) {
  376. return strvcat("0", &buffer[i], NULL);
  377. }
  378. if (flags & FLAG_HEX) {
  379. return strvcat((flags & FLAG_UPPER) ? "0X" : "0x", &buffer[i], NULL);
  380. }
  381. }
  382. return strdup(&buffer[i]);
  383. }
  384. static char *__format_int(int value, int flags) {
  385. char *string, *temp;
  386. if (value < 0) {
  387. temp = __format_uint(-value, flags);
  388. string = strvcat("-", temp, NULL);
  389. free(temp);
  390. }
  391. else {
  392. string = __format_uint(value, flags);
  393. }
  394. return string;
  395. }
  396. static char *__format_double_frac(long double value, int flags, int precision) {
  397. char *string;
  398. int i;
  399. if (value < 0) value = -value;
  400. if (value > 1) value -= floorl(value);
  401. string = malloc(precision + 1);
  402. for (i = 0; i < precision; i++) {
  403. value *= 10;
  404. string[i] = (int) value + '0';
  405. value -= floorl(value);
  406. if (value == 0.0 && !(flags & FLAG_ALT && flags & FLAG_MEXP)) {
  407. i++;
  408. break;
  409. }
  410. }
  411. string[i] = '\0';
  412. return string;
  413. }
  414. static char *__format_double_int(long double value, int flags) {
  415. char *temp, *string;
  416. int expt;
  417. expt = log10l(value) + 1;
  418. value /= (int) powl(10, expt);
  419. temp = __format_double_frac(value, flags | FLAG_ALT | FLAG_MEXP, expt);
  420. if (value < 0) {
  421. string = strvcat("-", temp, NULL);
  422. free(temp);
  423. }
  424. else if (flags & FLAG_SIGN) {
  425. string = strvcat("+", temp, NULL);
  426. free(temp);
  427. }
  428. else {
  429. string = temp;
  430. }
  431. return string;
  432. }
  433. static char *__format_double(long double value, int flags, int precision) {
  434. char *int_part;
  435. char *dec_part;
  436. char *string;
  437. long double i;
  438. if (isnan(value)) {
  439. if (flags & FLAG_UPPER) {
  440. return strdup("NAN");
  441. }
  442. else {
  443. return strdup("nan");
  444. }
  445. }
  446. if (isinf(value)) {
  447. if (flags & FLAG_UPPER) {
  448. if (value < 0) {
  449. return strdup("-INF");
  450. }
  451. else {
  452. if (flags & FLAG_SIGN) {
  453. return strdup("+INF");
  454. }
  455. else {
  456. return strdup("INF");
  457. }
  458. }
  459. }
  460. else {
  461. if (value < 0) {
  462. return strdup("-inf");
  463. }
  464. else {
  465. if (flags & FLAG_SIGN) {
  466. return strdup("+inf");
  467. }
  468. else {
  469. return strdup("inf");
  470. }
  471. }
  472. }
  473. }
  474. if (flags & FLAG_EXP || (flags & FLAG_MEXP && value > 1000000000)) {
  475. i = log10l(value);
  476. value /= powl(10, floorl(i));
  477. int_part = __format_double(value, flags & ~(FLAG_EXP), precision);
  478. dec_part = __format_int(i, flags | FLAG_SIGN);
  479. string = strvcat(int_part, (flags & FLAG_UPPER) ? "E" : "e", dec_part, NULL);
  480. free(int_part);
  481. free(dec_part);
  482. }
  483. else {
  484. value = modfl(value, &i);
  485. if (value > 2000000000) {
  486. int_part = __format_double_int(i, flags);
  487. }
  488. else {
  489. int_part = __format_int(i, flags);
  490. }
  491. dec_part = __format_double_frac(value, flags, precision);
  492. if (i == 0.0 && value < 0) {
  493. if (value != 0.0 || flags & FLAG_ALT) {
  494. string = strvcat("-", int_part, ".", dec_part, NULL);
  495. }
  496. else {
  497. string = strvcat("-", int_part, NULL);
  498. }
  499. }
  500. else {
  501. if (value != 0.0 || flags & FLAG_ALT) {
  502. string = strvcat(int_part, ".", dec_part, NULL);
  503. }
  504. else {
  505. string = strdup(int_part);
  506. }
  507. }
  508. free(int_part);
  509. free(dec_part);
  510. }
  511. return string;
  512. }
  513. size_t stream_putdouble(stream_s *stream, long double value, int precision, int flags)
  514. {
  515. char *string = __format_double(value, flags, precision);
  516. size_t len = strlen(string);
  517. stream_putstring(stream, string);
  518. free(string);
  519. return len;
  520. }
  521. /**********************************************************************/
  522. /**********************************************************************/
  523. static size_t stream_format_arg(stream_s *stream, const char **_fmt, va_list *argp)
  524. {
  525. int flags, type, length;
  526. size_t width, precision;
  527. const char *fmt = *_fmt;
  528. long double val_d;
  529. int val_i;
  530. unsigned int val_u;
  531. const char *val_s;
  532. char val_c;
  533. flags = 0;
  534. type = 0;
  535. width = 0;
  536. length = LENGTH_LONG;
  537. precision = 6;
  538. /* check for '%' */
  539. if (*fmt != '%') {
  540. return NULL;
  541. }
  542. /* read flags */
  543. do {
  544. fmt++;
  545. switch (*fmt) {
  546. case '+': flags |= FLAG_SIGN; continue;
  547. case '-': flags |= FLAG_LEFT; continue;
  548. case '#': flags |= FLAG_ALT; continue;
  549. case '0': flags |= FLAG_ZERO; continue;
  550. case '\0': return NULL;
  551. }
  552. break;
  553. } while (1);
  554. /* read width */
  555. if (*fmt == '*') {
  556. width = va_arg(*argp, int);
  557. fmt++;
  558. }
  559. else if (isdigit(*fmt)) {
  560. width = atoi(fmt);
  561. while (isdigit(*fmt)) fmt++;
  562. }
  563. /* read precision */
  564. if (*fmt == '.') {
  565. fmt++;
  566. if (*fmt == '*') {
  567. precision = va_arg(*argp, int);
  568. fmt++;
  569. }
  570. else if (isdigit(*fmt)) {
  571. precision = atoi(fmt);
  572. while (isdigit(*fmt)) fmt++;
  573. }
  574. else {
  575. return NULL;
  576. }
  577. }
  578. /* read length */
  579. switch (*fmt) {
  580. case 'h':
  581. fmt++;
  582. if (*fmt == 'h') {
  583. length = LENGTH_BYTE;
  584. fmt++;
  585. }
  586. else {
  587. length = LENGTH_SHORT;
  588. }
  589. break;
  590. case 'l':
  591. fmt++;
  592. if (*fmt == 'l') {
  593. length = LENGTH_LONG;
  594. fmt++;
  595. }
  596. else {
  597. length = LENGTH_LLONG;
  598. }
  599. break;
  600. case 'L': case 'j':
  601. length = LENGTH_LLONG;
  602. fmt++;
  603. break;
  604. case 'z': case 't':
  605. length = LENGTH_LONG;
  606. fmt++;
  607. case '\0':
  608. return NULL;
  609. }
  610. /* read type */
  611. switch (*fmt) {
  612. case 'i': case 'd':
  613. type = TYPE_INT;
  614. break;
  615. case 'u':
  616. type = TYPE_UINT;
  617. break;
  618. case 'F': flags |= FLAG_UPPER;
  619. case 'f':
  620. type = TYPE_DOUBLE;
  621. break;
  622. case 'G': flags |= FLAG_UPPER;
  623. case 'g':
  624. type = TYPE_DOUBLE;
  625. flags |= FLAG_MEXP;
  626. break;
  627. case 'E': flags |= FLAG_UPPER;
  628. case 'e':
  629. type = TYPE_DOUBLE;
  630. flags |= FLAG_EXP;
  631. break;
  632. case 'X': flags |= FLAG_UPPER;
  633. case 'x': case 'p':
  634. type = TYPE_UINT;
  635. flags |= FLAG_HEX;
  636. break;
  637. case 'O': flags |= FLAG_UPPER;
  638. case 'o':
  639. type = TYPE_UINT;
  640. flags |= FLAG_OCTAL;
  641. break;
  642. case 's':
  643. type = TYPE_STRING;
  644. break;
  645. case 'c':
  646. type = TYPE_CHAR;
  647. break;
  648. case '%':
  649. type = TYPE_LITERAL;
  650. break;
  651. default:
  652. return NULL;
  653. }
  654. /* read value */
  655. switch (type) {
  656. case TYPE_STRING: val_s = va_arg(*argp, const char *); break;
  657. case TYPE_CHAR: val_c = va_arg(*argp, char); break;
  658. case TYPE_LITERAL: val_c = '%'; break;
  659. case TYPE_INT: val_i = va_arg(*argp, int); break;
  660. case TYPE_UINT: val_u = va_arg(*argp, unsigned int); break;
  661. case TYPE_DOUBLE:
  662. if (length == LENGTH_LLONG) val_d = va_arg(*argp, long double);
  663. else val_d = va_arg(*argp, double);
  664. break;
  665. }
  666. /* create bytestream */
  667. stream_s *bs = bytestream_create(BUFSIZ);
  668. /* format value */
  669. switch (type) {
  670. case TYPE_STRING:
  671. stream_putstring(bs, val_s);
  672. break;
  673. case TYPE_CHAR: case TYPE_LITERAL:
  674. stream_putchar(bs, val_c);
  675. break;
  676. case TYPE_INT:
  677. stream_putint(bs, val_i, flags);
  678. break;
  679. case TYPE_UINT:
  680. stream_putuint(bs, val_u, flags);
  681. break;
  682. case TYPE_DOUBLE:
  683. stream_putdouble(bs, val_d, precision, flags);
  684. break;
  685. }
  686. /* get string data */
  687. size_t flen = bytestream_size(bs) - 1;
  688. char *fstr = (char *) bytestream_data(bs);
  689. if (flen < width) {
  690. if (flags & FLAG_LEFT)
  691. stream_putstring(stream, fstr);
  692. size_t i;
  693. for (i = 0; i < width - flen; i++)
  694. stream_putchar(stream, (flags & FLAG_ZERO) ? '0' : ' ');
  695. if (!(flags & FLAG_LEFT))
  696. stream_putstring(stream, fstr);
  697. } else {
  698. stream_putstring(stream, fstr);
  699. }
  700. *_fmt = fmt;
  701. return flen < width ? width : flen;
  702. }
  703. size_t stream_vformat(stream_s *stream, const char *format, va_list ap)
  704. {
  705. size_t i, count = 0;
  706. const char *format_tmp;
  707. for (i = 0; format[i]; i++) {
  708. if (format[i] != '%') {
  709. /* push non-formatting option */
  710. stream->put(stream, (unsigned char) format[i]);
  711. count++;
  712. continue;
  713. }
  714. format_tmp = &format[i]; /* format string location */
  715. count += stream_format_arg(stream, &format_tmp, &ap);
  716. i = (uintptr_t) format_tmp - (uintptr_t) format;
  717. }
  718. return 0;
  719. }
  720. size_t stream_format(stream_s *stream, const char *format, ...)
  721. {
  722. va_list ap;
  723. int ret;
  724. va_start(ap, format);
  725. ret = stream_vformat(stream, format, ap);
  726. va_end(ap);
  727. return ret;
  728. }