brdstr.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <bio.h>
  12. static char*
  13. badd(char *p, int *np, char *data, int ndata, int delim,
  14. int nulldelim)
  15. {
  16. int n;
  17. n = *np;
  18. p = realloc(p, n+ndata+1);
  19. if(p){
  20. memmove(p+n, data, ndata);
  21. n += ndata;
  22. if(n>0 && nulldelim && p[n-1]==delim)
  23. p[--n] = '\0';
  24. else
  25. p[n] = '\0';
  26. *np = n;
  27. }
  28. return p;
  29. }
  30. char*
  31. Brdstr(Biobufhdr *bp, int delim, int nulldelim)
  32. {
  33. char *ip, *ep, *p;
  34. int i, j;
  35. i = -bp->icount;
  36. bp->rdline = 0;
  37. if(i == 0) {
  38. /*
  39. * eof or other error
  40. */
  41. if(bp->state != Bractive) {
  42. if(bp->state == Bracteof)
  43. bp->state = Bractive;
  44. bp->gbuf = bp->ebuf;
  45. return nil;
  46. }
  47. }
  48. /*
  49. * first try in remainder of buffer (gbuf doesn't change)
  50. */
  51. ip = (char*)bp->ebuf - i;
  52. ep = memchr(ip, delim, i);
  53. if(ep) {
  54. j = (ep - ip) + 1;
  55. bp->icount += j;
  56. return badd(nil, &bp->rdline, ip, j, delim, nulldelim);
  57. }
  58. /*
  59. * copy data to beginning of buffer
  60. */
  61. if(i < bp->bsize)
  62. memmove(bp->bbuf, ip, i);
  63. bp->gbuf = bp->bbuf;
  64. /*
  65. * append to buffer looking for the delim
  66. */
  67. p = nil;
  68. for(;;){
  69. ip = (char*)bp->bbuf + i;
  70. while(i < bp->bsize) {
  71. j = read(bp->fid, ip, bp->bsize-i);
  72. if(j <= 0 && i == 0)
  73. return p;
  74. if(j <= 0 && i > 0){
  75. /*
  76. * end of file but no delim. pretend we got a delim
  77. * by making the delim \0 and smashing it with nulldelim.
  78. */
  79. j = 1;
  80. ep = ip;
  81. delim = '\0';
  82. nulldelim = 1;
  83. *ep = delim; /* there will be room for this */
  84. }else{
  85. bp->offset += j;
  86. ep = memchr(ip, delim, j);
  87. }
  88. i += j;
  89. if(ep) {
  90. /*
  91. * found in new piece
  92. * copy back up and reset everything
  93. */
  94. ip = (char*)bp->ebuf - i;
  95. if(i < bp->bsize){
  96. memmove(ip, bp->bbuf, i);
  97. bp->gbuf = (uint8_t*)ip;
  98. }
  99. j = (ep - (char*)bp->bbuf) + 1;
  100. bp->icount = j - i;
  101. return badd(p, &bp->rdline, ip, j, delim, nulldelim);
  102. }
  103. ip += j;
  104. }
  105. /*
  106. * full buffer without finding; add to user string and continue
  107. */
  108. p = badd(p, &bp->rdline, (char*)bp->bbuf, bp->bsize, 0,
  109. 0);
  110. i = 0;
  111. bp->icount = 0;
  112. bp->gbuf = bp->ebuf;
  113. }
  114. }