This commit is contained in:
2025-11-12 15:31:22 +08:00
parent 1dbe04cdf9
commit c317afc0fe
3 changed files with 53 additions and 44 deletions

View File

@@ -14,6 +14,7 @@
@property (nonatomic, assign) NSInteger decodedPrefixBytes; // sseTextBuffer SSE
@property (nonatomic, assign) NSInteger deliveredCharCount; // SSE
@property (nonatomic, assign) BOOL hasEmitted; // 1 \t
@property (nonatomic, assign) BOOL lastChunkEndedWithTab; // "\t" \t
@property (nonatomic, strong) NSMutableArray<NSString *> *pendingQueue; //
@property (nonatomic, strong) NSTimer *flushTimer; //
@property (nonatomic, strong, nullable) NSError *finishError; //
@@ -57,7 +58,7 @@ static NSUInteger kb_validUTF8PrefixLen(NSData *data) {
_buffer = [NSMutableData data];
_sseTextBuffer = [NSMutableString string];
_pendingQueue = [NSMutableArray array];
_flushInterval = 0.10;
_flushInterval = 0.1;
_splitLargeDeltasOnWhitespace = YES;
}
return self;
@@ -90,6 +91,7 @@ static NSUInteger kb_validUTF8PrefixLen(NSData *data) {
self.decodedPrefixBytes = 0;
self.deliveredCharCount = 0;
self.hasEmitted = NO;
self.lastChunkEndedWithTab = NO;
[self.pendingQueue removeAllObjects];
[self.flushTimer invalidate]; self.flushTimer = nil;
self.finishError = nil;
@@ -108,6 +110,7 @@ static NSUInteger kb_validUTF8PrefixLen(NSData *data) {
self.decodedPrefixBytes = 0;
self.deliveredCharCount = 0;
self.hasEmitted = NO;
self.lastChunkEndedWithTab = NO;
[self.pendingQueue removeAllObjects];
[self.flushTimer invalidate]; self.flushTimer = nil;
self.finishError = nil;
@@ -251,26 +254,37 @@ static NSUInteger kb_validUTF8PrefixLen(NSData *data) {
- (void)emitChunk:(NSString *)rawText {
if (rawText.length == 0) return;
NSString *text = rawText;
// 1) /t -> \t
if (self.treatSlashTAsTab) {
text = [text stringByReplacingOccurrencesOfString:@"/t" withString:@"\t"];
}
// 2) "\t"
if (!self.hasEmitted && self.trimLeadingTabOnce) {
// \t
NSUInteger i = 0;
while (i < text.length) {
unichar c = [text characterAtIndex:i];
if (c == ' ' || c == '\r' || c == '\n') { i++; continue; }
break;
}
if (i < text.length && [text characterAtIndex:i] == '\t') {
NSMutableString *m = [text mutableCopy];
[m deleteCharactersInRange:NSMakeRange(i, 1)];
text = m;
if (text.length > 0 && [text characterAtIndex:0] == '\t') {
NSUInteger start = 1;
if (start < text.length && [text characterAtIndex:start] == ' ') start++;
text = [text substringFromIndex:start];
}
}
if (text.length == 0) return;
// 3) \t -> \t
if (text.length > 0) {
// \t
if (self.lastChunkEndedWithTab) {
NSUInteger j = 0;
while (j < text.length && [text characterAtIndex:j] == ' ') { j++; }
if (j > 0) {
text = [text substringFromIndex:1]; //
}
}
// \t \t
text = [text stringByReplacingOccurrencesOfString:@"\t " withString:@"\t"];
}
if (text.length == 0) { self.lastChunkEndedWithTab = NO; return; }
if (self.onChunk) dispatch_async(dispatch_get_main_queue(), ^{ self.onChunk(text); });
self.hasEmitted = YES;
// \t
unichar lastc = [text characterAtIndex:text.length - 1];
self.lastChunkEndedWithTab = (lastc == '\t');
}
#pragma mark - Queue/Flush