mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
Implement -[NSString enumerateLinesUsingBlock:] (#407)
* Implement -[NSString enumerateLinesUsingBlock:] * Fix formatting * Use GNUstep CALL_BLOCK macro
This commit is contained in:
parent
c498475110
commit
4d3926d250
5 changed files with 133 additions and 1 deletions
|
@ -5,6 +5,13 @@
|
|||
Improve implementation of BETWEEN operator in NSPredicate
|
||||
for data types other than NSNumber. Proper support
|
||||
for constant values.
|
||||
|
||||
2024-05-18 Hugo Melder <hugo@algoriddim.com>
|
||||
|
||||
* Source/NSString.m:
|
||||
* Headers/Foundation/NSString.h:
|
||||
* Tests/base/NSString/enumerateLinesUsingBlock.m:
|
||||
Implemented -[NSString enumerateLinesUsingBlock:].
|
||||
|
||||
2024-04-30 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
|
|
|
@ -466,6 +466,7 @@ enum {
|
|||
typedef NSUInteger NSStringEnumerationOptions;
|
||||
|
||||
DEFINE_BLOCK_TYPE(GSNSStringEnumerationBlock, void, NSString* substring, NSRange substringRange, NSRange enclosingRange, BOOL* stop);
|
||||
DEFINE_BLOCK_TYPE(GSNSStringLineEnumerationBlock, void, NSString *line, BOOL *stop);
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -1093,6 +1094,9 @@ GS_EXPORT_CLASS
|
|||
#endif /* GS_API_NONE */
|
||||
|
||||
#if OS_API_VERSION(MAC_OS_X_VERSION_10_6,GS_API_LATEST)
|
||||
|
||||
- (void) enumerateLinesUsingBlock: (GSNSStringLineEnumerationBlock)block;
|
||||
|
||||
- (void) enumerateSubstringsInRange: (NSRange)range
|
||||
options: (NSStringEnumerationOptions)opts
|
||||
usingBlock: (GSNSStringEnumerationBlock)block;
|
||||
|
|
1
MISSING
1
MISSING
|
@ -552,7 +552,6 @@ NSString:
|
|||
- lowercaseStringWithLocale:
|
||||
- capitalizedStringWithLocale:
|
||||
- enumerateSubstringsInRange:options:usingBlock:
|
||||
- enumerateLinesUsingBlock:
|
||||
- getBytes:maxLength:usedLength:encoding:options:range:remainingRange:
|
||||
- decomposedStringWithCanonicalMapping
|
||||
- precomposedStringWithCanonicalMapping
|
||||
|
|
|
@ -6271,6 +6271,39 @@ static NSFileManager *fm = nil;
|
|||
return [self rangeOfString: string].location != NSNotFound;
|
||||
}
|
||||
|
||||
- (void) enumerateLinesUsingBlock: (GSNSStringLineEnumerationBlock)block
|
||||
{
|
||||
NSUInteger length;
|
||||
NSUInteger lineStart, lineEnd, contentsEnd;
|
||||
NSRange currentLocationRange;
|
||||
BOOL stop;
|
||||
|
||||
length = [self length];
|
||||
lineStart = lineEnd = contentsEnd = 0;
|
||||
stop = NO;
|
||||
|
||||
// Enumerate through the string line by line
|
||||
while (lineStart < length && !stop) {
|
||||
NSString *line;
|
||||
NSRange lineRange;
|
||||
|
||||
currentLocationRange = NSMakeRange(lineStart, 0);
|
||||
[self getLineStart: &lineStart
|
||||
end: &lineEnd
|
||||
contentsEnd: &contentsEnd
|
||||
forRange: currentLocationRange];
|
||||
|
||||
lineRange = NSMakeRange(lineStart, contentsEnd - lineStart);
|
||||
line = [self substringWithRange: lineRange];
|
||||
|
||||
// Execute the block
|
||||
CALL_BLOCK(block, line, &stop);
|
||||
|
||||
// Move to the next line
|
||||
lineStart = lineEnd;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) enumerateSubstringsInRange: (NSRange)range
|
||||
options: (NSStringEnumerationOptions)opts
|
||||
usingBlock: (GSNSStringEnumerationBlock)block
|
||||
|
|
89
Tests/base/NSString/enumerateLinesUsingBlock.m
Normal file
89
Tests/base/NSString/enumerateLinesUsingBlock.m
Normal file
|
@ -0,0 +1,89 @@
|
|||
#import <Foundation/NSAutoreleasePool.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSArray.h>
|
||||
|
||||
#import "Testing.h"
|
||||
|
||||
#if defined(__has_extension) && __has_extension(blocks)
|
||||
|
||||
BOOL testEnumerateSimpleLines() {
|
||||
NSString *testString = @"First line\nSecond line\nThird line";
|
||||
NSMutableArray *collectedLines = [NSMutableArray array];
|
||||
NSArray *expectedLines = @[@"First line", @"Second line", @"Third line"];
|
||||
|
||||
[testString enumerateLinesUsingBlock: ^(NSString *line, BOOL *stop) {
|
||||
[collectedLines addObject: line];
|
||||
}];
|
||||
|
||||
return [collectedLines isEqualToArray: expectedLines];
|
||||
}
|
||||
|
||||
BOOL testEnumerateCRLFLines() {
|
||||
NSString *testString = @"First line\r\nSecond line\r\nThird line";
|
||||
NSMutableArray *collectedLines = [NSMutableArray array];
|
||||
NSArray *expectedLines = @[@"First line", @"Second line", @"Third line"];
|
||||
|
||||
[testString enumerateLinesUsingBlock: ^(NSString *line, BOOL *stop) {
|
||||
[collectedLines addObject: line];
|
||||
}];
|
||||
|
||||
return [collectedLines isEqualToArray: expectedLines];
|
||||
}
|
||||
|
||||
BOOL testStopEarly() {
|
||||
NSString *testString = @"First line\nSecond line\nThird line";
|
||||
__block int lineCount = 0;
|
||||
|
||||
[testString enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) {
|
||||
lineCount++;
|
||||
if ([line isEqualToString:@"Second line"]) {
|
||||
*stop = YES;
|
||||
}
|
||||
}];
|
||||
|
||||
return lineCount == 2; // Should stop after the second line
|
||||
}
|
||||
|
||||
BOOL testEmptyString() {
|
||||
NSString *testString = @"";
|
||||
__block BOOL blockCalled = NO;
|
||||
|
||||
[testString enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) {
|
||||
blockCalled = YES;
|
||||
}];
|
||||
|
||||
return !blockCalled; // Block should not be called
|
||||
}
|
||||
|
||||
BOOL testSingleLineNoBreaks() {
|
||||
NSString *testString = @"Single line without line breaks";
|
||||
__block NSString *receivedLine = nil;
|
||||
|
||||
[testString enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) {
|
||||
receivedLine = line;
|
||||
}];
|
||||
|
||||
return [receivedLine isEqualToString:testString];
|
||||
}
|
||||
|
||||
int main() {
|
||||
NSAutoreleasePool *arp = [NSAutoreleasePool new];
|
||||
|
||||
PASS(testEnumerateSimpleLines(), "Should enumerate all lines correctly.");
|
||||
PASS(testEnumerateCRLFLines(), "Should enumerate all CRLF lines correctly.");
|
||||
PASS(testStopEarly(), "Should stop enumeration early as directed.");
|
||||
PASS(testEmptyString(), "Should not call block for empty string.");
|
||||
PASS(testSingleLineNoBreaks(), "Should handle single line without line breaks correctly.");
|
||||
|
||||
[arp release];
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main (int argc, const char * argv[])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue