ObjFW  Check-in [28942b4055]

Overview
Comment:OFINIFile: Use URLs instead of paths
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 28942b40559ac0dfa12635f8ee03bd7a9a9f15754b328dd9fcc64c6130b86720
User & Date: js on 2022-08-07 15:59:38
Other Links: manifest | tags
Context
2022-08-07
16:04
tests: Embed testfile.ini as well check-in: 942f77abbe user: js tags: trunk
15:59
OFINIFile: Use URLs instead of paths check-in: 28942b4055 user: js tags: trunk
15:47
OFSystemInfo: Use URLs for system directories check-in: a5f2e3d0a5 user: js tags: trunk
Changes

Modified src/OFINIFile.h from [85f822e023] to [de47c3e875].

16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

44
45
46
47

48
49
50
51
52
53

54
55
56
57
58
59

60
61
62
63
64
65
66
67

68
69
70
71

72
73
74
75
76
77

78
79
80
81
82
83


84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

101
102

103
104
105
106
107
108

109
110
111

112
113
114
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

44
45
46
47

48
49
50
51
52
53

54
55
56
57
58


59
60
61
62
63
64
65
66

67
68
69
70

71
72
73
74
75
76

77
78
79
80
81


82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

100
101

102
103
104
105
106
107

108
109
110

111
112
113
114







+




















-
+



-
+





-
+




-
-
+







-
+



-
+





-
+




-
-
+
+
















-
+

-
+





-
+


-
+



#import "OFObject.h"
#import "OFString.h"
#import "OFINICategory.h"

OF_ASSUME_NONNULL_BEGIN

@class OFMutableArray OF_GENERIC(ObjectType);
@class OFURL;

/**
 * @class OFINIFile OFINIFile.h ObjFW/OFINIFile.h
 *
 * @brief A class for reading, creating and modifying INI files.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFINIFile: OFObject
{
	OFMutableArray OF_GENERIC(OFINICategory *) *_categories;
}

/**
 * @brief All categories in the INI file.
 */
@property (readonly, nonatomic) OFArray OF_GENERIC(OFINICategory *) *categories;

/**
 * @brief Creates a new OFINIFile with the contents of the specified file.
 *
 * @param path The path to the file whose contents the OFINIFile should contain
 * @param URL The URL to the file whose contents the OFINIFile should contain
 *
 * @return A new, autoreleased OFINIFile with the contents of the specified file
 */
+ (instancetype)fileWithPath: (OFString *)path;
+ (instancetype)fileWithURL: (OFURL *)URL;

/**
 * @brief Creates a new OFINIFile with the contents of the specified file in
 *	  the specified encoding.
 *
 * @param path The path to the file whose contents the OFINIFile should contain
 * @param URL The URL to the file whose contents the OFINIFile should contain
 * @param encoding The encoding of the specified file
 *
 * @return A new, autoreleased OFINIFile with the contents of the specified file
 */
+ (instancetype)fileWithPath: (OFString *)path
		    encoding: (OFStringEncoding)encoding;
+ (instancetype)fileWithURL: (OFURL *)URL encoding: (OFStringEncoding)encoding;

- (instancetype)init OF_UNAVAILABLE;

/**
 * @brief Initializes an already allocated OFINIFile with the contents of the
 *	  specified file.
 *
 * @param path The path to the file whose contents the OFINIFile should contain
 * @param URL The URL to the file whose contents the OFINIFile should contain
 *
 * @return An initialized OFINIFile with the contents of the specified file
 */
- (instancetype)initWithPath: (OFString *)path;
- (instancetype)initWithURL: (OFURL *)URL;

/**
 * @brief Initializes an already allocated OFINIFile with the contents of the
 *	  specified file in the specified encoding.
 *
 * @param path The path to the file whose contents the OFINIFile should contain
 * @param URL The URL to the file whose contents the OFINIFile should contain
 * @param encoding The encoding of the specified file
 *
 * @return An initialized OFINIFile with the contents of the specified file
 */
- (instancetype)initWithPath: (OFString *)path
		    encoding: (OFStringEncoding)encoding
- (instancetype)initWithURL: (OFURL *)URL
		   encoding: (OFStringEncoding)encoding
    OF_DESIGNATED_INITIALIZER;

/**
 * @brief Returns an @ref OFINICategory for the category with the specified
 *	  name.
 *
 * @param name The name of the category for which an @ref OFINICategory should
 *	       be returned
 *
 * @return An @ref OFINICategory for the category with the specified name
 */
- (OFINICategory *)categoryForName: (OFString *)name;

/**
 * @brief Writes the contents of the OFINIFile to a file.
 *
 * @param path The path of the file to write to
 * @param URL The URL of the file to write to
 */
- (void)writeToFile: (OFString *)path;
- (void)writeToURL: (OFURL *)URL;

/**
 * @brief Writes the contents of the OFINIFile to a file in the specified
 *	  encoding.
 *
 * @param path The path of the file to write to
 * @param URL The URL of the file to write to
 * @param encoding The encoding to use
 */
- (void)writeToFile: (OFString *)path encoding: (OFStringEncoding)encoding;
- (void)writeToURL: (OFURL *)URL encoding: (OFStringEncoding)encoding;
@end

OF_ASSUME_NONNULL_END

Modified src/OFINIFile.m from [f3dcfaef7e] to [5568ad8169].

15
16
17
18
19
20
21

22
23
24
25





26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

52
53

54
55
56
57

58
59

60
61
62
63
64
65
66
67
68

69
70

71
72
73
74

75
76
77
78
79
80
81

82
83
84
85
86
87
88
15
16
17
18
19
20
21
22




23
24
25
26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

53
54

55
56
57


58
59

60

61
62
63
64
65
66
67

68
69

70
71
72


73
74
75
76
77
78
79

80
81
82
83
84
85
86
87







+
-
-
-
-
+
+
+
+
+






-
+


















-
+

-
+


-
-
+

-
+
-







-
+

-
+


-
-
+






-
+








#include "config.h"

#include <errno.h>

#import "OFINIFile.h"
#import "OFArray.h"
#import "OFINICategory+Private.h"
#import "OFString.h"
#import "OFFile.h"
#import "OFINICategory.h"
#import "OFINICategory+Private.h"
#import "OFINICategory.h"
#import "OFStream.h"
#import "OFString.h"
#import "OFURL.h"
#import "OFURLHandler.h"

#import "OFInvalidFormatException.h"
#import "OFOpenItemFailedException.h"

OF_DIRECT_MEMBERS
@interface OFINIFile ()
- (void)of_parseFile: (OFString *)path encoding: (OFStringEncoding)encoding;
- (void)of_parseURL: (OFURL *)URL encoding: (OFStringEncoding)encoding;
@end

static bool
isWhitespaceLine(OFString *line)
{
	const char *cString = line.UTF8String;
	size_t length = line.UTF8StringLength;

	for (size_t i = 0; i < length; i++)
		if (!OFASCIIIsSpace(cString[i]))
			return false;

	return true;
}

@implementation OFINIFile
@synthesize categories = _categories;

+ (instancetype)fileWithPath: (OFString *)path
+ (instancetype)fileWithURL: (OFURL *)URL
{
	return [[[self alloc] initWithPath: path] autorelease];
	return [[[self alloc] initWithURL: URL] autorelease];
}

+ (instancetype)fileWithPath: (OFString *)path
		    encoding: (OFStringEncoding)encoding
+ (instancetype)fileWithURL: (OFURL *)URL encoding: (OFStringEncoding)encoding
{
	return [[[self alloc] initWithPath: path
	return [[[self alloc] initWithURL: URL encoding: encoding] autorelease];
				  encoding: encoding] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)initWithPath: (OFString *)path
- (instancetype)initWithURL: (OFURL *)URL
{
	return [self initWithPath: path encoding: OFStringEncodingUTF8];
	return [self initWithURL: URL encoding: OFStringEncodingAutodetect];
}

- (instancetype)initWithPath: (OFString *)path
		    encoding: (OFStringEncoding)encoding
- (instancetype)initWithURL: (OFURL *)URL encoding: (OFStringEncoding)encoding
{
	self = [super init];

	@try {
		_categories = [[OFMutableArray alloc] init];

		[self of_parseFile: path encoding: encoding];
		[self of_parseURL: URL encoding: encoding];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}
107
108
109
110
111
112
113
114

115
116
117

118
119
120
121

122

123
124
125
126
127
128
129
106
107
108
109
110
111
112

113
114
115

116
117
118
119
120
121

122
123
124
125
126
127
128
129







-
+


-
+




+
-
+







	[_categories addObject: category];

	objc_autoreleasePoolPop(pool);

	return category;
}

- (void)of_parseFile: (OFString *)path encoding: (OFStringEncoding)encoding
- (void)of_parseURL: (OFURL *)URL encoding: (OFStringEncoding)encoding
{
	void *pool = objc_autoreleasePoolPush();
	OFFile *file;
	OFStream *file;
	OFINICategory *category = nil;
	OFString *line;

	@try {
		file = [[OFURLHandler handlerForURL: URL] openItemAtURL: URL
		file = [OFFile fileWithPath: path mode: @"r"];
								   mode: @"r"];
	} @catch (OFOpenItemFailedException *e) {
		/* Handle missing file like an empty file */
		if (e.errNo == ENOENT)
			return;

		@throw e;
	}
150
151
152
153
154
155
156
157

158
159

160
161
162

163
164


165

166
167
168
169
170
171
172
150
151
152
153
154
155
156

157
158

159
160
161

162
163
164
165
166

167
168
169
170
171
172
173
174







-
+

-
+


-
+


+
+
-
+







			[category of_parseLine: line];
		}
	}

	objc_autoreleasePoolPop(pool);
}

- (void)writeToFile: (OFString *)path
- (void)writeToURL: (OFURL *)URL
{
	[self writeToFile: path encoding: OFStringEncodingUTF8];
	[self writeToURL: URL encoding: OFStringEncodingUTF8];
}

- (void)writeToFile: (OFString *)path encoding: (OFStringEncoding)encoding
- (void)writeToURL: (OFURL *)URL encoding: (OFStringEncoding)encoding
{
	void *pool = objc_autoreleasePoolPush();
	OFStream *file = [[OFURLHandler handlerForURL: URL]
	    openItemAtURL: URL
	OFFile *file = [OFFile fileWithPath: path mode: @"w"];
		     mode: @"w"];
	bool first = true;

	for (OFINICategory *category in _categories)
		if ([category of_writeToStream: file
				      encoding: encoding
					 first: first])
			first = false;

Modified src/OFINIFileSettings.h from [1f5bf8dc61] to [e6622a40c7].

13
14
15
16
17
18
19

20
21

22
23
24
25

26
27
28
29
30
13
14
15
16
17
18
19
20
21

22
23
24
25

26
27
28
29
30
31







+

-
+



-
+





 * file.
 */

#import "OFSettings.h"

OF_ASSUME_NONNULL_BEGIN

@class OFINIFile;
@class OFString;
@class OFINIFile;
@class OFURL;

@interface OFINIFileSettings: OFSettings
{
	OFString *_filePath;
	OFURL *_fileURL;
	OFINIFile *_INIFile;
}
@end

OF_ASSUME_NONNULL_END

Modified src/OFINIFileSettings.m from [449e841772] to [06a12ac82c].

28
29
30
31
32
33
34
35

36
37
38


39
40
41
42
43
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
28
29
30
31
32
33
34

35



36
37
38
39
40
41
42
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57







-
+
-
-
-
+
+












-
+







	self = [super initWithApplicationName: applicationName];

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFString *fileName;

		fileName = [applicationName stringByAppendingString: @".ini"];
		_filePath = [[[OFSystemInfo
		_fileURL = [[[OFSystemInfo userConfigURL]
		    userConfigURL].fileSystemRepresentation
		    stringByAppendingPathComponent: fileName] copy];
		_INIFile = [[OFINIFile alloc] initWithPath: _filePath];
		    URLByAppendingPathComponent: fileName] copy];
		_INIFile = [[OFINIFile alloc] initWithURL: _fileURL];

		objc_autoreleasePoolPop(pool);
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

- (void)dealloc
{
	[_filePath release];
	[_fileURL release];
	[_INIFile release];

	[super dealloc];
}

- (void)of_getCategory: (OFString **)category
		andKey: (OFString **)key
240
241
242
243
244
245
246
247

248
249
239
240
241
242
243
244
245

246
247
248







-
+


	[[_INIFile categoryForName: category] removeValueForKey: key];

	objc_autoreleasePoolPop(pool);
}

- (void)save
{
	[_INIFile writeToFile: _filePath];
	[_INIFile writeToURL: _fileURL];
}
@end

Modified tests/OFINIFileTests.m from [cd30a90cdd] to [0f67b17e7c].

39
40
41
42
43
44
45

46
47
48
49
50

51
52
53
54

55
56
57



58
59
60
61
62
63
64
39
40
41
42
43
44
45
46
47
48
49
50

51
52
53
54
55
56



57
58
59
60
61
62
63
64
65
66







+




-
+




+
-
-
-
+
+
+







	    @"[types]\r\n"
	    @"integer=16\r\n"
	    @"bool=false\r\n"
	    @"float=0.25\r\n"
	    @"array1=foo\r\n"
	    @"array1=bar\r\n"
	    @"double=0.75\r\n";
	OFURL *URL;
	OFINIFile *file;
	OFINICategory *tests, *foobar, *types;
	OFArray *array;
#ifndef OF_NINTENDO_DS
	OFString *writePath;
	OFURL *writeURL;
#endif

	module = @"OFINIFile";

	URL = [OFURL fileURLWithPath: @"testfile.ini"];
	TEST(@"+[fileWithPath:encoding:]",
	    (file = [OFINIFile fileWithPath: @"testfile.ini"
				   encoding: OFStringEncodingCodepage437]))
	TEST(@"+[fileWithURL:encoding:]",
	    (file = [OFINIFile fileWithURL: URL
				  encoding: OFStringEncodingCodepage437]))

	tests = [file categoryForName: @"tests"];
	foobar = [file categoryForName: @"foobar"];
	types = [file categoryForName: @"types"];
	TEST(@"-[categoryForName:]",
	    tests != nil && foobar != nil && types != nil)

110
111
112
113
114
115
116
117

118
119

120
121
122
123
124
125




126
127

128
129
130
131
132
133
134
112
113
114
115
116
117
118

119
120

121

122




123
124
125
126
127

128
129
130
131
132
133
134
135







-
+

-
+
-

-
-
-
-
+
+
+
+

-
+







	    R([foobar removeValueForKey: @"quxqux "]) &&
	    R([types removeValueForKey: @"array2"]))

	module = @"OFINIFile";

	/* FIXME: Find a way to write files on Nintendo DS */
#ifndef OF_NINTENDO_DS
	writePath = [[OFSystemInfo temporaryDirectoryURL]
	writeURL = [[OFSystemInfo temporaryDirectoryURL]
	    URLByAppendingPathComponent: @"objfw-tests.ini"
			    isDirectory: false]
			    isDirectory: false];
	    .fileSystemRepresentation;
	TEST(@"-[writeToFile:encoding:]",
	    R([file writeToFile: writePath
		       encoding: OFStringEncodingCodepage437]) &&
	    [[OFString stringWithContentsOfFile: writePath
				       encoding: OFStringEncodingCodepage437]
	    R([file writeToURL: writeURL
		      encoding: OFStringEncodingCodepage437]) &&
	    [[OFString stringWithContentsOfURL: writeURL
				      encoding: OFStringEncodingCodepage437]
	    isEqual: output])
	[[OFFileManager defaultManager] removeItemAtPath: writePath];
	[[OFFileManager defaultManager] removeItemAtURL: writeURL];
#else
	(void)output;
#endif

	objc_autoreleasePoolPop(pool);
}
@end