| 263 | } |
| 264 | |
| 265 | func (sw *StreamWriter) Write(p []byte) (int, error) { |
| 266 | sw.mu.Lock() |
| 267 | defer sw.mu.Unlock() |
| 268 | |
| 269 | sw.buf = append(sw.buf, p...) |
| 270 | for { |
| 271 | idx := bytes.IndexByte(sw.buf, '\n') |
| 272 | if idx < 0 { |
| 273 | break |
| 274 | } |
| 275 | line := string(sw.buf[:idx]) |
| 276 | line = strings.TrimSuffix(line, "\r") |
| 277 | if sw.onOutput != nil { |
| 278 | sw.onOutput(line) |
| 279 | } |
| 280 | sw.buf = sw.buf[idx+1:] |
| 281 | } |
| 282 | // Flush oversized buffers to avoid unbounded memory |
| 283 | if len(sw.buf) > 4096 { |
| 284 | if sw.onOutput != nil { |
| 285 | sw.onOutput(string(sw.buf)) |
| 286 | } |
| 287 | sw.buf = sw.buf[:0] |
| 288 | } |
| 289 | return len(p), nil |
| 290 | } |
| 291 | |
| 292 | // Flush emits any remaining buffered content as a final line. |
| 293 | func (sw *StreamWriter) Flush() { |