brdstr.c 2.0 KB

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