test-scm-c-read.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /* Copyright 2008,2014,2018
  2. Free Software Foundation, Inc.
  3. This file is part of Guile.
  4. Guile is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Lesser General Public License as published
  6. by the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. Guile is distributed in the hope that it will be useful, but WITHOUT
  9. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  11. License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with Guile. If not, see
  14. <https://www.gnu.org/licenses/>. */
  15. /* Exercise `scm_c_read ()' and the port type API. Verify assumptions that
  16. can be made by port type implementations. */
  17. #ifdef HAVE_CONFIG_H
  18. # include <config.h>
  19. #endif
  20. #undef NDEBUG
  21. #include <assert.h>
  22. #include <string.h>
  23. #include <libguile.h>
  24. /* Size of our port's internal buffer. */
  25. #define PORT_BUFFER_SIZE 1024
  26. struct custom_port
  27. {
  28. size_t pos;
  29. size_t len;
  30. char *buf;
  31. };
  32. /* Return a new port of type PORT_TYPE. */
  33. static inline SCM
  34. make_port (scm_t_port_type *port_type)
  35. {
  36. struct custom_port *stream = scm_gc_typed_calloc (struct custom_port);
  37. stream->pos = 0;
  38. stream->len = PORT_BUFFER_SIZE;
  39. stream->buf = scm_gc_calloc (stream->len, "custom-port-buffer");
  40. return scm_c_make_port (port_type, SCM_RDNG, (scm_t_bits) stream);
  41. }
  42. static size_t
  43. custom_port_read (SCM port, SCM dst, size_t start, size_t count)
  44. {
  45. size_t to_copy = count;
  46. struct custom_port *stream = (void *) SCM_STREAM (port);
  47. if (stream->pos + to_copy > stream->len)
  48. to_copy = stream->len - stream->pos;
  49. memcpy (SCM_BYTEVECTOR_CONTENTS (dst) + start,
  50. stream->buf + stream->pos, to_copy);
  51. stream->pos += to_copy;
  52. return to_copy;
  53. }
  54. /* Return true (non-zero) if BUF contains only zeros. */
  55. static inline int
  56. zeroed_buffer_p (const char *buf, size_t len)
  57. {
  58. size_t i;
  59. for (i = 0; i < len; i++)
  60. if (buf[i] != 0)
  61. return 0;
  62. return 1;
  63. }
  64. /* Run the test. */
  65. static void *
  66. do_start (void *arg)
  67. {
  68. SCM port;
  69. scm_t_port_type *port_type;
  70. char buffer[PORT_BUFFER_SIZE + (PORT_BUFFER_SIZE / 2)];
  71. size_t read, last_read;
  72. port_type = scm_make_port_type ("custom-input-port", custom_port_read, NULL);
  73. port = make_port (port_type);
  74. read = 0;
  75. do
  76. {
  77. last_read = scm_c_read (port, &buffer[read], 123);
  78. assert (last_read <= 123);
  79. assert (zeroed_buffer_p (&buffer[read], last_read));
  80. read += last_read;
  81. }
  82. while (last_read > 0 && read < sizeof (buffer));
  83. /* We shouldn't be able to read more than what's in PORT's buffer. */
  84. assert (read == PORT_BUFFER_SIZE);
  85. return NULL;
  86. }
  87. int
  88. main (int argc, char *argv[])
  89. {
  90. scm_with_guile (do_start, NULL);
  91. return 0;
  92. }