brdstr.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #include "lib9.h"
  2. #include <bio.h>
  3. static char*
  4. badd(char *p, int *np, char *data, int ndata, int delim, int nulldelim)
  5. {
  6. int n;
  7. n = *np;
  8. p = realloc(p, n+ndata+1);
  9. if(p){
  10. memmove(p+n, data, ndata);
  11. n += ndata;
  12. if(n>0 && nulldelim && p[n-1]==delim)
  13. p[--n] = '\0';
  14. else
  15. p[n] = '\0';
  16. *np = n;
  17. }
  18. return p;
  19. }
  20. char*
  21. Brdstr(Biobuf *bp, int delim, int nulldelim)
  22. {
  23. char *ip, *ep, *p;
  24. int i, j;
  25. i = -bp->icount;
  26. bp->rdline = 0;
  27. if(i == 0) {
  28. /*
  29. * eof or other error
  30. */
  31. if(bp->state != Bractive) {
  32. if(bp->state == Bracteof)
  33. bp->state = Bractive;
  34. bp->gbuf = bp->ebuf;
  35. return nil;
  36. }
  37. }
  38. /*
  39. * first try in remainder of buffer (gbuf doesn't change)
  40. */
  41. ip = (char*)bp->ebuf - i;
  42. ep = memchr(ip, delim, i);
  43. if(ep) {
  44. j = (ep - ip) + 1;
  45. bp->icount += j;
  46. return badd(nil, &bp->rdline, ip, j, delim, nulldelim);
  47. }
  48. /*
  49. * copy data to beginning of buffer
  50. */
  51. if(i < bp->bsize)
  52. memmove(bp->bbuf, ip, i);
  53. bp->gbuf = bp->bbuf;
  54. /*
  55. * append to buffer looking for the delim
  56. */
  57. p = nil;
  58. for(;;){
  59. ip = (char*)bp->bbuf + i;
  60. while(i < bp->bsize) {
  61. j = read(bp->fid, ip, bp->bsize-i);
  62. if(j <= 0 && i == 0)
  63. return p;
  64. if(j <= 0 && i > 0){
  65. /*
  66. * end of file but no delim. pretend we got a delim
  67. * by making the delim \0 and smashing it with nulldelim.
  68. */
  69. j = 1;
  70. ep = ip;
  71. delim = '\0';
  72. nulldelim = 1;
  73. *ep = delim; /* there will be room for this */
  74. }else{
  75. bp->offset += j;
  76. ep = memchr(ip, delim, j);
  77. }
  78. i += j;
  79. if(ep) {
  80. /*
  81. * found in new piece
  82. * copy back up and reset everything
  83. */
  84. ip = (char*)bp->ebuf - i;
  85. if(i < bp->bsize){
  86. memmove(ip, bp->bbuf, i);
  87. bp->gbuf = (uchar*)ip;
  88. }
  89. j = (ep - (char*)bp->bbuf) + 1;
  90. bp->icount = j - i;
  91. return badd(p, &bp->rdline, ip, j, delim, nulldelim);
  92. }
  93. ip += j;
  94. }
  95. /*
  96. * full buffer without finding; add to user string and continue
  97. */
  98. p = badd(p, &bp->rdline, (char*)bp->bbuf, bp->bsize, 0, 0);
  99. i = 0;
  100. bp->icount = 0;
  101. bp->gbuf = bp->ebuf;
  102. }
  103. }