ObjFW  Diff

Differences From Artifact [cb70217adb]:

  • File src/OFEmbeddedIRIHandler.m — part of check-in [9d802a786d] at 2025-01-01 12:58:18 on branch trunk — Update copyright (user: js size: 4315) [more...]

To Artifact [bd63da2d45]:

  • File src/OFEmbeddedIRIHandler.m — part of check-in [83237c1826] at 2025-03-15 09:10:18 on branch trunk — OFEmbeddedIRIHandler: Optimize lookup (user: js size: 5039) [more...]

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
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
115
116
117
118







+
+

















-
-
+
+
+




















-
-
-
+
+
+

-
-
-
-
+
+
+
+





+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







#include "config.h"

#include <errno.h>
#include <stdlib.h>
#include <string.h>

#import "OFEmbeddedIRIHandler.h"
#import "OFData.h"
#import "OFDictionary.h"
#import "OFIRI.h"
#import "OFMemoryStream.h"
#import "OFNumber.h"

#import "OFGetItemAttributesFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFOpenItemFailedException.h"

#ifdef OF_HAVE_THREADS
# import "OFOnce.h"
# import "OFPlainMutex.h"
#endif

static struct EmbeddedFile {
	OFString *path;
	const uint8_t *bytes;
	size_t size;
} *embeddedFiles = NULL;
static size_t numEmbeddedFiles = 0;
} *embeddedFilesQueue = NULL;
static size_t embeddedFilesQueueCount = 0;
static OFMutableDictionary *embeddedFiles = nil;
#ifdef OF_HAVE_THREADS
static OFPlainMutex mutex;
static OFOnceControl mutexOnceControl = OFOnceControlInitValue;

static void
initMutex(void)
{
	OFEnsure(OFPlainMutexNew(&mutex) == 0);
}
#endif

void
OFRegisterEmbeddedFile(OFString *path, const uint8_t *bytes, size_t size)
{
#ifdef OF_HAVE_THREADS
	OFOnce(&mutexOnceControl, initMutex);

	OFEnsure(OFPlainMutexLock(&mutex) == 0);
#endif

	embeddedFiles = realloc(embeddedFiles,
	    sizeof(*embeddedFiles) * (numEmbeddedFiles + 1));
	OFEnsure(embeddedFiles != NULL);
	embeddedFilesQueue = realloc(embeddedFilesQueue,
	    sizeof(*embeddedFilesQueue) * (embeddedFilesQueueCount + 1));
	OFEnsure(embeddedFilesQueue != NULL);

	embeddedFiles[numEmbeddedFiles].path = path;
	embeddedFiles[numEmbeddedFiles].bytes = bytes;
	embeddedFiles[numEmbeddedFiles].size = size;
	numEmbeddedFiles++;
	embeddedFilesQueue[embeddedFilesQueueCount].path = path;
	embeddedFilesQueue[embeddedFilesQueueCount].bytes = bytes;
	embeddedFilesQueue[embeddedFilesQueueCount].size = size;
	embeddedFilesQueueCount++;

#ifdef OF_HAVE_THREADS
	OFEnsure(OFPlainMutexUnlock(&mutex) == 0);
#endif
}

static void
processQueueLocked(void)
{
	void *pool;

	if (embeddedFilesQueueCount == 0)
		return;

	if (embeddedFiles == nil)
		embeddedFiles = [[OFMutableDictionary alloc] init];

	pool = objc_autoreleasePoolPush();

	for (size_t i = 0; i < embeddedFilesQueueCount; i++) {
		OFData *data = [OFData
		    dataWithItemsNoCopy: (void *)embeddedFilesQueue[i].bytes
				  count: embeddedFilesQueue[i].size
			   freeWhenDone: false];

		[embeddedFiles setObject: data
				  forKey: embeddedFilesQueue[i].path];
	}

	free(embeddedFilesQueue);
	embeddedFilesQueue = NULL;
	embeddedFilesQueueCount = 0;

	objc_autoreleasePoolPop(pool);
}

@implementation OFEmbeddedIRIHandler
#ifdef OF_HAVE_THREADS
+ (void)initialize
{
	if (self == [OFEmbeddedIRIHandler class])
		OFOnce(&mutexOnceControl, initMutex);
104
105
106
107
108
109
110
111
112
113



114

115
116

117
118

119
120
121
122
123
124
125
126
127
137
138
139
140
141
142
143



144
145
146
147
148
149

150


151
152

153
154
155
156
157
158
159







-
-
-
+
+
+

+

-
+
-
-
+

-







		@throw [OFInvalidArgumentException exception];
	}

#ifdef OF_HAVE_THREADS
	OFEnsure(OFPlainMutexLock(&mutex) == 0);
	@try {
#endif
		for (size_t i = 0; i < numEmbeddedFiles; i++) {
			if (![embeddedFiles[i].path isEqual: path])
				continue;
		OFData *data;

		processQueueLocked();

		if ((data = [embeddedFiles objectForKey: path]) != nil)
			return [OFMemoryStream
			    streamWithMemoryAddress: (void *)
			    streamWithMemoryAddress: (void *)data.items
							 embeddedFiles[i].bytes
					       size: embeddedFiles[i].size
					       size: data.count
					   writable: false];
		}
#ifdef OF_HAVE_THREADS
	} @finally {
		OFEnsure(OFPlainMutexUnlock(&mutex) == 0);
	}
#endif

	@throw [OFOpenItemFailedException exceptionWithIRI: IRI
142
143
144
145
146
147
148
149
150

151
152
153

154


155

156
157
158
159
160
161
162
163
174
175
176
177
178
179
180


181
182


183
184
185
186

187

188
189
190
191
192
193
194







-
-
+

-
-
+

+
+
-
+
-







		@throw [OFInvalidArgumentException exception];
	}

#ifdef OF_HAVE_THREADS
	OFEnsure(OFPlainMutexLock(&mutex) == 0);
	@try {
#endif
		for (size_t i = 0; i < numEmbeddedFiles; i++) {
			OFNumber *fileSize;
		OFData *data;

			if (![embeddedFiles[i].path isEqual: path])
				continue;
		processQueueLocked();

		if ((data = [embeddedFiles objectForKey: path]) != nil) {
			OFNumber *fileSize = [OFNumber
			fileSize = [OFNumber numberWithUnsignedLongLong:
			    numberWithUnsignedLongLong: data.count];
			    embeddedFiles[i].size];

			return [OFDictionary dictionaryWithKeysAndObjects:
			    OFFileSize, fileSize,
			    OFFileType, OFFileTypeRegular,
			    nil];
		}
#ifdef OF_HAVE_THREADS