ObjFW  Diff

Differences From Artifact [92fb9ca7c6]:

To Artifact [34d1acfa38]:


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
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







-
-
+
+
+









-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+








#import "OFInvalidArgumentException.h"
#import "OFInvalidFormatException.h"
#import "OFOutOfRangeException.h"

@interface OFNumber ()
+ (instancetype)of_alloc;
- (OFString *)of_JSONRepresentationWithOptions: (int)options
					 depth: (size_t)depth;
- (OFString *)
    of_JSONRepresentationWithOptions: (OFJSONRepresentationOptions)options
			       depth: (size_t)depth;
@end

@interface OFNumberPlaceholder: OFNumber
@end

@interface OFNumberSingleton: OFNumber
@end

#ifdef OF_OBJFW_RUNTIME
enum {
	TAG_CHAR,
	TAG_SHORT,
	TAG_INT,
	TAG_LONG,
	TAG_LONG_LONG,
	TAG_UNSIGNED_CHAR,
	TAG_UNSIGNED_SHORT,
	TAG_UNSIGNED_INT,
	TAG_UNSIGNED_LONG,
	TAG_UNSIGNED_LONG_LONG,
enum Tag {
	tagChar,
	tagShort,
	tagInt,
	tagLong,
	tagLongLong,
	tagUnsignedChar,
	tagUnsignedShort,
	tagUnsignedInt,
	tagUnsignedLong,
	tagUnsignedLongLong,
};
# define TAG_BITS 4
# define TAG_MASK 0xF
static const uint_fast8_t tagBits = 4;
static const uintptr_t tagMask = 0xF;

@interface OFTaggedPointerNumber: OFNumberSingleton
@end
#endif

static struct {
	Class isa;
146
147
148
149
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

175
176

177
178
179
180
181
182
183
184
185
186
187
188
189
190


191
192
193

194
195

196
197
198
199
200
201
202
203
204
205
206
207
208
209


210
211
212

213
214

215
216
217
218
219
220
221
222
223
224
225
226
227
228


229
230
231

232
233

234
235
236
237
238
239
240
241
242
243
244
245
246
247


248
249
250

251
252
253


254
255
256
257
258
259
260
261
262
263
264
265
266
267


268
269
270

271
272

273
274
275
276
277
278
279
280
281
282
283
284
285
286


287
288
289

290
291

292
293
294
295
296
297
298
299
300
301
302
303
304
305


306
307
308

309
310

311
312
313
314
315
316
317
318
319
320
321
322
323
324


325
326
327

328
329

330
331
332
333
334
335
336
337
338
339
340
341
342
343


344
345
346

347
348

349
350
351
352
353
354
355
356
357
358
359
360
361
362


363
364
365
366
367
368
369
370
371
372
373


374
375
376
377
378
379
380
147
148
149
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

175
176

177
178
179
180
181
182
183
184
185
186
187
188
189


190
191
192
193

194
195

196
197
198
199
200
201
202
203
204
205
206
207
208


209
210
211
212

213
214

215
216
217
218
219
220
221
222
223
224
225
226
227


228
229
230
231

232
233

234
235
236
237
238
239
240
241
242
243
244
245
246


247
248
249
250

251
252


253
254
255
256
257
258
259
260
261
262
263
264
265
266


267
268
269
270

271
272

273
274
275
276
277
278
279
280
281
282
283
284
285


286
287
288
289

290
291

292
293
294
295
296
297
298
299
300
301
302
303
304


305
306
307
308

309
310

311
312
313
314
315
316
317
318
319
320
321
322
323


324
325
326
327

328
329

330
331
332
333
334
335
336
337
338
339
340
341
342


343
344
345
346

347
348

349
350
351
352
353
354
355
356
357
358
359
360
361


362
363
364
365
366
367
368
369
370
371
372


373
374
375
376
377
378
379
380
381







-
-
+
+


-
-
+
+











-
-
+
+


-
+

-
+












-
-
+
+


-
+

-
+












-
-
+
+


-
+

-
+












-
-
+
+


-
+

-
+












-
-
+
+


-
+

-
-
+
+












-
-
+
+


-
+

-
+












-
-
+
+


-
+

-
+












-
-
+
+


-
+

-
+












-
-
+
+


-
+

-
+












-
-
+
+


-
+

-
+












-
-
+
+









-
-
+
+







	}
}

@implementation OFNumberPlaceholder
- (instancetype)initWithBool: (bool)value
{
	if (value) {
		static of_once_t once = OF_ONCE_INIT;
		of_once(&once, trueNumberInit);
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, trueNumberInit);
		return (id)trueNumber;
	} else {
		static of_once_t once = OF_ONCE_INIT;
		of_once(&once, falseNumberInit);
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, falseNumberInit);
		return (id)falseNumber;
	}
}

#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare"
#endif
- (instancetype)initWithChar: (signed char)value
{
	if (value == 0) {
		static of_once_t once = OF_ONCE_INIT;
		of_once(&once, charZeroNumberInit);
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, charZeroNumberInit);
		return (id)charZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if ((unsigned char)value <= (UINTPTR_MAX >> TAG_BITS)) {
	} else if ((unsigned char)value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)(unsigned char)value << TAG_BITS) | TAG_CHAR);
		    ((uintptr_t)(unsigned char)value << tagBits) | tagChar);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithChar: value];
}

- (instancetype)initWithShort: (short)value
{
	if (value == 0) {
		static of_once_t once = OF_ONCE_INIT;
		of_once(&once, shortZeroNumberInit);
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, shortZeroNumberInit);
		return (id)shortZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if ((unsigned short)value <= (UINTPTR_MAX >> TAG_BITS)) {
	} else if ((unsigned short)value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)(unsigned short)value << TAG_BITS) | TAG_SHORT);
		    ((uintptr_t)(unsigned short)value << tagBits) | tagShort);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithShort: value];
}

- (instancetype)initWithInt: (int)value
{
	if (value == 0) {
		static of_once_t once = OF_ONCE_INIT;
		of_once(&once, intZeroNumberInit);
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, intZeroNumberInit);
		return (id)intZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if ((unsigned int)value <= (UINTPTR_MAX >> TAG_BITS)) {
	} else if ((unsigned int)value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)(unsigned int)value << TAG_BITS) | TAG_INT);
		    ((uintptr_t)(unsigned int)value << tagBits) | tagInt);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithInt: value];
}

- (instancetype)initWithLong: (long)value
{
	if (value == 0) {
		static of_once_t once = OF_ONCE_INIT;
		of_once(&once, longZeroNumberInit);
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, longZeroNumberInit);
		return (id)longZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if ((unsigned long)value <= (UINTPTR_MAX >> TAG_BITS)) {
	} else if ((unsigned long)value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)(unsigned long)value << TAG_BITS) | TAG_LONG);
		    ((uintptr_t)(unsigned long)value << tagBits) | tagLong);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithLong: value];
}

- (instancetype)initWithLongLong: (long long)value
{
	if (value == 0) {
		static of_once_t once = OF_ONCE_INIT;
		of_once(&once, longLongZeroNumberInit);
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, longLongZeroNumberInit);
		return (id)longLongZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if ((unsigned long long)value <= (UINTPTR_MAX >> TAG_BITS)) {
	} else if ((unsigned long long)value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)(unsigned long long)value << TAG_BITS) |
		    TAG_LONG_LONG);
		    ((uintptr_t)(unsigned long long)value << tagBits) |
		    tagLongLong);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithLongLong: value];
}

- (instancetype)initWithUnsignedChar: (unsigned char)value
{
	if (value == 0) {
		static of_once_t once = OF_ONCE_INIT;
		of_once(&once, unsignedCharZeroNumberInit);
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, unsignedCharZeroNumberInit);
		return (id)unsignedCharZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if (value <= (UINTPTR_MAX >> TAG_BITS)) {
	} else if (value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)value << TAG_BITS) | TAG_UNSIGNED_CHAR);
		    ((uintptr_t)value << tagBits) | tagUnsignedChar);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithUnsignedChar: value];
}

- (instancetype)initWithUnsignedShort: (unsigned short)value
{
	if (value == 0) {
		static of_once_t once = OF_ONCE_INIT;
		of_once(&once, unsignedShortZeroNumberInit);
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, unsignedShortZeroNumberInit);
		return (id)unsignedShortZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if (value <= (UINTPTR_MAX >> TAG_BITS)) {
	} else if (value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)value << TAG_BITS) | TAG_UNSIGNED_SHORT);
		    ((uintptr_t)value << tagBits) | tagUnsignedShort);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithUnsignedShort: value];
}

- (instancetype)initWithUnsignedInt: (unsigned int)value
{
	if (value == 0) {
		static of_once_t once = OF_ONCE_INIT;
		of_once(&once, unsignedIntZeroNumberInit);
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, unsignedIntZeroNumberInit);
		return (id)unsignedIntZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if (value <= (UINTPTR_MAX >> TAG_BITS)) {
	} else if (value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)value << TAG_BITS) | TAG_UNSIGNED_INT);
		    ((uintptr_t)value << tagBits) | tagUnsignedInt);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithUnsignedInt: value];
}

- (instancetype)initWithUnsignedLong: (unsigned long)value
{
	if (value == 0) {
		static of_once_t once = OF_ONCE_INIT;
		of_once(&once, unsignedLongZeroNumberInit);
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, unsignedLongZeroNumberInit);
		return (id)unsignedLongZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if (value <= (UINTPTR_MAX >> TAG_BITS)) {
	} else if (value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)value << TAG_BITS) | TAG_UNSIGNED_LONG);
		    ((uintptr_t)value << tagBits) | tagUnsignedLong);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithUnsignedLong: value];
}

- (instancetype)initWithUnsignedLongLong: (unsigned long long)value
{
	if (value == 0) {
		static of_once_t once = OF_ONCE_INIT;
		of_once(&once, unsignedLongLongZeroNumberInit);
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, unsignedLongLongZeroNumberInit);
		return (id)unsignedLongLongZeroNumber;
#ifdef OF_OBJFW_RUNTIME
	} else if (value <= (UINTPTR_MAX >> TAG_BITS)) {
	} else if (value <= (UINTPTR_MAX >> tagBits)) {
		id ret = objc_createTaggedPointer(numberTag,
		    ((uintptr_t)value << TAG_BITS) | TAG_UNSIGNED_LONG_LONG);
		    ((uintptr_t)value << tagBits) | tagUnsignedLongLong);

		if (ret != nil)
			return ret;
#endif
	}

	return (id)[[OFNumber of_alloc] initWithUnsignedLongLong: value];
}

- (instancetype)initWithFloat: (float)value
{
	if (value == 0) {
		static of_once_t once = OF_ONCE_INIT;
		of_once(&once, floatZeroNumberInit);
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, floatZeroNumberInit);
		return (id)floatZeroNumber;
	}

	return (id)[[OFNumber of_alloc] initWithFloat: value];
}

- (instancetype)initWithDouble: (double)value
{
	if (value == 0) {
		static of_once_t once = OF_ONCE_INIT;
		of_once(&once, doubleZeroNumberInit);
		static OFOnceControl onceControl = OFOnceControlInitValue;
		OFOnce(&onceControl, doubleZeroNumberInit);
		return (id)doubleZeroNumber;
	}

	return (id)[[OFNumber of_alloc] initWithDouble: value];
}

- (instancetype)initWithSerialization: (OFXMLElement *)element
399
400
401
402
403
404
405
406

407
408
409
410
411
412
413
414
415
416
417


418
419

420
421

422
423

424
425

426
427

428
429

430
431

432
433

434
435

436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467


























468
469
470
471
472
473
474
400
401
402
403
404
405
406

407
408
409
410
411
412
413
414
415
416


417
418
419

420
421

422
423

424
425

426
427

428
429

430
431

432
433

434
435

436
437
438
439
440
441
442


























443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475







-
+









-
-
+
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+

-
+






-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+








- (void)release
{
}

- (unsigned int)retainCount
{
	return OF_RETAIN_COUNT_MAX;
	return OFMaxRetainCount;
}
@end

#ifdef OF_OBJFW_RUNTIME
@implementation OFTaggedPointerNumber
- (const char *)objCType
{
	uintptr_t value = object_getTaggedPointerValue(self);

	switch (value & TAG_MASK) {
	case TAG_CHAR:
	switch (value & tagMask) {
	case tagChar:
		return @encode(signed char);
	case TAG_SHORT:
	case tagShort:
		return @encode(short);
	case TAG_INT:
	case tagInt:
		return @encode(int);
	case TAG_LONG:
	case tagLong:
		return @encode(long);
	case TAG_LONG_LONG:
	case tagLongLong:
		return @encode(long long);
	case TAG_UNSIGNED_CHAR:
	case tagUnsignedChar:
		return @encode(unsigned char);
	case TAG_UNSIGNED_SHORT:
	case tagUnsignedShort:
		return @encode(unsigned short);
	case TAG_UNSIGNED_INT:
	case tagUnsignedInt:
		return @encode(unsigned int);
	case TAG_UNSIGNED_LONG:
	case tagUnsignedLong:
		return @encode(unsigned long);
	case TAG_UNSIGNED_LONG_LONG:
	case tagUnsignedLongLong:
		return @encode(unsigned long long);
	default:
		@throw [OFInvalidArgumentException exception];
	}
}

# define RETURN_VALUE							   \
	uintptr_t value = object_getTaggedPointerValue(self);		   \
									   \
	switch (value & TAG_MASK) {					   \
	case TAG_CHAR:							   \
		return (signed char)(unsigned char)(value >> TAG_BITS);	   \
	case TAG_SHORT:							   \
		return (short)(unsigned short)(value >> TAG_BITS);	   \
	case TAG_INT:							   \
		return (int)(unsigned int)(value >> TAG_BITS);		   \
	case TAG_LONG:							   \
		return (long)(unsigned long)(value >> TAG_BITS);	   \
	case TAG_LONG_LONG:						   \
		return (long long)(unsigned long long)(value >> TAG_BITS); \
	case TAG_UNSIGNED_CHAR:						   \
		return (unsigned char)(value >> TAG_BITS);		   \
	case TAG_UNSIGNED_SHORT:					   \
		return (unsigned short)(value >> TAG_BITS);		   \
	case TAG_UNSIGNED_INT:						   \
		return (unsigned int)(value >> TAG_BITS);		   \
	case TAG_UNSIGNED_LONG:						   \
		return (unsigned long)(value >> TAG_BITS);		   \
	case TAG_UNSIGNED_LONG_LONG:					   \
		return (unsigned long long)(value >> TAG_BITS);		   \
	default:							   \
		@throw [OFInvalidArgumentException exception];		   \
# define RETURN_VALUE							  \
	uintptr_t value = object_getTaggedPointerValue(self);		  \
									  \
	switch (value & tagMask) {					  \
	case tagChar:							  \
		return (signed char)(unsigned char)(value >> tagBits);	  \
	case tagShort:							  \
		return (short)(unsigned short)(value >> tagBits);	  \
	case tagInt:							  \
		return (int)(unsigned int)(value >> tagBits);		  \
	case tagLong:							  \
		return (long)(unsigned long)(value >> tagBits);		  \
	case tagLongLong:						  \
		return (long long)(unsigned long long)(value >> tagBits); \
	case tagUnsignedChar:						  \
		return (unsigned char)(value >> tagBits);		  \
	case tagUnsignedShort:						  \
		return (unsigned short)(value >> tagBits);		  \
	case tagUnsignedInt:						  \
		return (unsigned int)(value >> tagBits);		  \
	case tagUnsignedLong:						  \
		return (unsigned long)(value >> tagBits);		  \
	case tagUnsignedLongLong:					  \
		return (unsigned long long)(value >> tagBits);		  \
	default:							  \
		@throw [OFInvalidArgumentException exception];		  \
	}
- (long long)longLongValue
{
	RETURN_VALUE
}

- (unsigned long long)unsignedLongLongValue
746
747
748
749
750
751
752
753

754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774


775
776
777
778
779
780
781
747
748
749
750
751
752
753

754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773


774
775
776
777
778
779
780
781
782







-
+



















-
-
+
+







	self = [super init];

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

		if (![element.name isEqual: @"OFNumber"] ||
		    ![element.namespace isEqual: OF_SERIALIZATION_NS])
		    ![element.namespace isEqual: OFSerializationNS])
			@throw [OFInvalidArgumentException exception];

		typeString = [element attributeForName: @"type"].stringValue;

		if ([typeString isEqual: @"bool"]) {
			OFString *stringValue = element.stringValue;
			if ([stringValue isEqual: @"true"])
				self = [self initWithBool: true];
			else if ([stringValue isEqual: @"false"])
				self = [self initWithBool: false];
			else
				@throw [OFInvalidArgumentException exception];
		} else if ([typeString isEqual: @"float"]) {
			unsigned long long value =
			    [element unsignedLongLongValueWithBase: 16];

			if (value > UINT64_MAX)
				@throw [OFOutOfRangeException exception];

			self = [self initWithDouble: OF_BSWAP_DOUBLE_IF_LE(
			    OF_INT_TO_DOUBLE_RAW(OF_BSWAP64_IF_LE(value)))];
			self = [self initWithDouble: OFFromBigEndianDouble(
			    OFRawUInt64ToDouble(OFToBigEndian64(value)))];
		} else if ([typeString isEqual: @"signed"])
			self = [self initWithLongLong: element.longLongValue];
		else if ([typeString isEqual: @"unsigned"])
			self = [self initWithUnsignedLongLong:
			    element.unsignedLongLongValue];
		else
			@throw [OFInvalidArgumentException exception];
790
791
792
793
794
795
796
797

798
799
800
801
802
803
804
805
791
792
793
794
795
796
797

798

799
800
801
802
803
804
805







-
+
-







}

- (const char *)objCType
{
	return _typeEncoding;
}

- (void)getValue: (void *)value
- (void)getValue: (void *)value size: (size_t)size
	    size: (size_t)size
{
	switch (*self.objCType) {
#define CASE(enc, type, property)					\
	case enc: {							\
		type tmp = (type)self.property;				\
									\
		if (size != sizeof(type))				\
939
940
941
942
943
944
945
946
947
948
949
950



951
952
953
954
955
956
957
958
959
960

961
962

963
964

965
966
967
968
969
970

971
972

973
974

975
976
977
978
979
980

981
982

983
984

985
986
987
988
989
990

991
992

993
994
995
996
997
998
999
1000

1001
1002
1003

1004
1005
1006
1007
1008

1009
1010
1011
1012
1013
1014

1015
1016
1017
1018
1019
1020
1021
939
940
941
942
943
944
945





946
947
948
949


950
951
952
953
954
955

956
957

958
959

960
961
962
963
964
965

966
967

968
969

970
971
972
973
974
975

976
977

978
979

980
981
982
983
984
985

986
987

988
989
990
991
992
993
994
995

996
997
998

999
1000
1001
1002
1003

1004
1005
1006
1007
1008
1009

1010
1011
1012
1013
1014
1015
1016
1017







-
-
-
-
-
+
+
+

-
-






-
+

-
+

-
+





-
+

-
+

-
+





-
+

-
+

-
+





-
+

-
+







-
+


-
+




-
+





-
+








	if (isSigned(self) || isSigned(number))
		return (number.longLongValue == self.longLongValue);

	return (number.unsignedLongLongValue == self.unsignedLongLongValue);
}

- (of_comparison_result_t)compare: (id <OFComparing>)object
{
	OFNumber *number;

	if (![(id)object isKindOfClass: [OFNumber class]])
- (OFComparisonResult)compare: (OFNumber *)number
{
	if (![number isKindOfClass: [OFNumber class]])
		@throw [OFInvalidArgumentException exception];

	number = (OFNumber *)object;

	if (isFloat(self) || isFloat(number)) {
		double double1 = self.doubleValue;
		double double2 = number.doubleValue;

		if (double1 > double2)
			return OF_ORDERED_DESCENDING;
			return OFOrderedDescending;
		if (double1 < double2)
			return OF_ORDERED_ASCENDING;
			return OFOrderedAscending;

		return OF_ORDERED_SAME;
		return OFOrderedSame;
	} else if (isSigned(self) || isSigned(number)) {
		long long int1 = self.longLongValue;
		long long int2 = number.longLongValue;

		if (int1 > int2)
			return OF_ORDERED_DESCENDING;
			return OFOrderedDescending;
		if (int1 < int2)
			return OF_ORDERED_ASCENDING;
			return OFOrderedAscending;

		return OF_ORDERED_SAME;
		return OFOrderedSame;
	} else {
		unsigned long long uint1 = self.unsignedLongLongValue;
		unsigned long long uint2 = number.unsignedLongLongValue;

		if (uint1 > uint2)
			return OF_ORDERED_DESCENDING;
			return OFOrderedDescending;
		if (uint1 < uint2)
			return OF_ORDERED_ASCENDING;
			return OFOrderedAscending;

		return OF_ORDERED_SAME;
		return OFOrderedSame;
	}
}

- (unsigned long)hash
{
	uint32_t hash;
	unsigned long hash;

	OF_HASH_INIT(hash);
	OFHashInit(&hash);

	if (isFloat(self)) {
		double d;

		if (isnan(self.doubleValue))
			return 0;

		d = OF_BSWAP_DOUBLE_IF_BE(self.doubleValue);
		d = OFToLittleEndianDouble(self.doubleValue);

		for (uint_fast8_t i = 0; i < sizeof(double); i++)
			OF_HASH_ADD(hash, ((char *)&d)[i]);
			OFHashAdd(&hash, ((char *)&d)[i]);
	} else if (isSigned(self) || isUnsigned(self)) {
		unsigned long long value = self.unsignedLongLongValue;

		while (value != 0) {
			OF_HASH_ADD(hash, value & 0xFF);
			OFHashAdd(&hash, value & 0xFF);
			value >>= 8;
		}
	} else
		@throw [OFInvalidFormatException exception];

	OF_HASH_FINALIZE(hash);
	OFHashFinalize(&hash);

	return hash;
}

- (id)copy
{
	return [self retain];
1043
1044
1045
1046
1047
1048
1049
1050

1051
1052
1053
1054

1055
1056
1057

1058
1059
1060
1061

1062
1063
1064

1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081

1082
1083
1084
1085


1086
1087

1088
1089
1090
1091
1092



1093
1094
1095
1096
1097
1098
1099
1100
1101

1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121

1122
1123
1124
1125

1126
1127

1128
1129
1130
1131

1132
1133
1134
1135

1136
1137

1138
1139
1140
1141

1142
1143
1144
1145
1146
1147
1148
1149

1150
1151
1152
1153
1154
1155

1156
1157
1158
1159
1160
1161
1162

1163
1164

1165
1166
1167
1168

1169
1170
1171
1172

1173
1174

1175
1176
1177
1178

1179
1180
1181
1182

1183
1184

1185
1186
1187
1188

1189
1190
1191
1192
1193
1194
1195
1196
1197
1198

1199
1200
1201
1202
1203
1204

1205
1206
1207
1208
1209
1210
1211

1212
1213

1214
1215
1216
1217

1218
1219
1220
1221

1222
1223

1224
1225
1226
1227

1228
1229
1230
1231

1232
1233

1234
1235
1236
1237

1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1039
1040
1041
1042
1043
1044
1045

1046
1047
1048
1049

1050

1051

1052

1053
1054

1055
1056
1057

1058

1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073

1074

1075
1076

1077
1078
1079

1080

1081
1082


1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093

1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112


1113

1114
1115

1116
1117

1118


1119

1120

1121
1122

1123
1124

1125


1126

1127

1128
1129
1130
1131
1132
1133

1134

1135
1136
1137
1138

1139


1140
1141
1142
1143

1144
1145

1146


1147

1148

1149
1150

1151
1152

1153


1154

1155

1156
1157

1158
1159

1160


1161

1162

1163
1164
1165
1166
1167
1168
1169


1170

1171
1172
1173
1174

1175


1176
1177
1178
1179

1180
1181

1182


1183

1184

1185
1186

1187
1188

1189


1190

1191

1192
1193

1194
1195

1196


1197

1198

1199
1200
1201
1202
1203
1204
1205
1206
1207
1208







-
+



-
+
-

-
+
-


-
+


-
+
-















-
+
-


-
+
+

-
+
-


-
-
+
+
+








-
+


















-
-
+
-


-
+

-
+
-
-

-
+
-


-
+

-
+
-
-

-
+
-






-
+
-




-
+
-
-




-
+

-
+
-
-

-
+
-


-
+

-
+
-
-

-
+
-


-
+

-
+
-
-

-
+
-







-
-
+
-




-
+
-
-




-
+

-
+
-
-

-
+
-


-
+

-
+
-
-

-
+
-


-
+

-
+
-
-

-
+
-











- (OFXMLElement *)XMLElementBySerializing
{
	void *pool = objc_autoreleasePoolPush();
	OFXMLElement *element;

	element = [OFXMLElement elementWithName: @"OFNumber"
				      namespace: OF_SERIALIZATION_NS
				      namespace: OFSerializationNS
				    stringValue: self.description];

	if (*self.objCType == 'B')
		[element addAttributeWithName: @"type"
		[element addAttributeWithName: @"type" stringValue: @"bool"];
				  stringValue: @"bool"];
	else if (isFloat(self)) {
		[element addAttributeWithName: @"type"
		[element addAttributeWithName: @"type" stringValue: @"float"];
				  stringValue: @"float"];
		element.stringValue = [OFString
		    stringWithFormat: @"%016" PRIx64,
		    OF_BSWAP64_IF_LE(OF_DOUBLE_TO_INT_RAW(OF_BSWAP_DOUBLE_IF_LE(
		    OFFromBigEndian64(OFDoubleToRawUInt64(OFToBigEndianDouble(
		    self.doubleValue)))];
	} else if (isSigned(self))
		[element addAttributeWithName: @"type"
		[element addAttributeWithName: @"type" stringValue: @"signed"];
				  stringValue: @"signed"];
	else if (isUnsigned(self))
		[element addAttributeWithName: @"type"
				  stringValue: @"unsigned"];
	else
		@throw [OFInvalidFormatException exception];

	[element retain];

	objc_autoreleasePoolPop(pool);

	return [element autorelease];
}

- (OFString *)JSONRepresentation
{
	return [self of_JSONRepresentationWithOptions: 0
	return [self of_JSONRepresentationWithOptions: 0 depth: 0];
						depth: 0];
}

- (OFString *)JSONRepresentationWithOptions: (int)options
- (OFString *)JSONRepresentationWithOptions:
    (OFJSONRepresentationOptions)options
{
	return [self of_JSONRepresentationWithOptions: options
	return [self of_JSONRepresentationWithOptions: options depth: 0];
						depth: 0];
}

- (OFString *)of_JSONRepresentationWithOptions: (int)options
					 depth: (size_t)depth
- (OFString *)
    of_JSONRepresentationWithOptions: (OFJSONRepresentationOptions)options
			       depth: (size_t)depth
{
	double doubleValue;

	if (*self.objCType == 'B')
		return (self.boolValue ? @"true" : @"false");

	doubleValue = self.doubleValue;
	if (isinf(doubleValue)) {
		if (options & OF_JSON_REPRESENTATION_JSON5) {
		if (options & OFJSONRepresentationOptionJSON5) {
			if (doubleValue > 0)
				return @"Infinity";
			else
				return @"-Infinity";
		} else
			@throw [OFInvalidArgumentException exception];
	}

	return self.description;
}

- (OFData *)messagePackRepresentation
{
	OFMutableData *data;
	const char *typeEncoding = self.objCType;

	if (*typeEncoding == 'B') {
		uint8_t type = (self.boolValue ? 0xC3 : 0xC2);

		data = [OFMutableData dataWithItems: &type
		data = [OFMutableData dataWithItems: &type count: 1];
					      count: 1];
	} else if (*typeEncoding == 'f') {
		uint8_t type = 0xCA;
		float tmp = OF_BSWAP_FLOAT_IF_LE(self.floatValue);
		float tmp = OFToBigEndianFloat(self.floatValue);

		data = [OFMutableData dataWithItemSize: 1
		data = [OFMutableData dataWithCapacity: 5];
					      capacity: 5];

		[data addItem: &type];
		[data addItems: &tmp
		[data addItems: &tmp count: sizeof(tmp)];
			 count: sizeof(tmp)];
	} else if (*typeEncoding == 'd') {
		uint8_t type = 0xCB;
		double tmp = OF_BSWAP_DOUBLE_IF_LE(self.doubleValue);
		double tmp = OFToBigEndianDouble(self.doubleValue);

		data = [OFMutableData dataWithItemSize: 1
		data = [OFMutableData dataWithCapacity: 9];
					      capacity: 9];

		[data addItem: &type];
		[data addItems: &tmp
		[data addItems: &tmp count: sizeof(tmp)];
			 count: sizeof(tmp)];
	} else if (isSigned(self)) {
		long long value = self.longLongValue;

		if (value >= -32 && value < 0) {
			uint8_t tmp = 0xE0 | ((uint8_t)(value - 32) & 0x1F);

			data = [OFMutableData dataWithItems: &tmp
			data = [OFMutableData dataWithItems: &tmp count: 1];
						      count: 1];
		} else if (value >= INT8_MIN && value <= INT8_MAX) {
			uint8_t type = 0xD0;
			int8_t tmp = (int8_t)value;

			data = [OFMutableData dataWithItemSize: 1
			data = [OFMutableData dataWithCapacity: 2];
						      capacity: 2];

			[data addItem: &type];
			[data addItem: &tmp];
		} else if (value >= INT16_MIN && value <= INT16_MAX) {
			uint8_t type = 0xD1;
			int16_t tmp = OF_BSWAP16_IF_LE((int16_t)value);
			int16_t tmp = OFToBigEndian16((int16_t)value);

			data = [OFMutableData dataWithItemSize: 1
			data = [OFMutableData dataWithCapacity: 3];
						      capacity: 3];

			[data addItem: &type];
			[data addItems: &tmp
			[data addItems: &tmp count: sizeof(tmp)];
				 count: sizeof(tmp)];
		} else if (value >= INT32_MIN && value <= INT32_MAX) {
			uint8_t type = 0xD2;
			int32_t tmp = OF_BSWAP32_IF_LE((int32_t)value);
			int32_t tmp = OFToBigEndian32((int32_t)value);

			data = [OFMutableData dataWithItemSize: 1
			data = [OFMutableData dataWithCapacity: 5];
						      capacity: 5];

			[data addItem: &type];
			[data addItems: &tmp
			[data addItems: &tmp count: sizeof(tmp)];
				 count: sizeof(tmp)];
		} else if (value >= INT64_MIN && value <= INT64_MAX) {
			uint8_t type = 0xD3;
			int64_t tmp = OF_BSWAP64_IF_LE((int64_t)value);
			int64_t tmp = OFToBigEndian64((int64_t)value);

			data = [OFMutableData dataWithItemSize: 1
			data = [OFMutableData dataWithCapacity: 9];
						      capacity: 9];

			[data addItem: &type];
			[data addItems: &tmp
			[data addItems: &tmp count: sizeof(tmp)];
				 count: sizeof(tmp)];
		} else
			@throw [OFOutOfRangeException exception];
	} else if (isUnsigned(self)) {
		unsigned long long value = self.unsignedLongLongValue;

		if (value <= 127) {
			uint8_t tmp = ((uint8_t)value & 0x7F);

			data = [OFMutableData dataWithItems: &tmp
			data = [OFMutableData dataWithItems: &tmp count: 1];
						      count: 1];
		} else if (value <= UINT8_MAX) {
			uint8_t type = 0xCC;
			uint8_t tmp = (uint8_t)value;

			data = [OFMutableData dataWithItemSize: 1
			data = [OFMutableData dataWithCapacity: 2];
						      capacity: 2];

			[data addItem: &type];
			[data addItem: &tmp];
		} else if (value <= UINT16_MAX) {
			uint8_t type = 0xCD;
			uint16_t tmp = OF_BSWAP16_IF_LE((uint16_t)value);
			uint16_t tmp = OFToBigEndian16((uint16_t)value);

			data = [OFMutableData dataWithItemSize: 1
			data = [OFMutableData dataWithCapacity: 3];
						      capacity: 3];

			[data addItem: &type];
			[data addItems: &tmp
			[data addItems: &tmp count: sizeof(tmp)];
				 count: sizeof(tmp)];
		} else if (value <= UINT32_MAX) {
			uint8_t type = 0xCE;
			uint32_t tmp = OF_BSWAP32_IF_LE((uint32_t)value);
			uint32_t tmp = OFToBigEndian32((uint32_t)value);

			data = [OFMutableData dataWithItemSize: 1
			data = [OFMutableData dataWithCapacity: 5];
						      capacity: 5];

			[data addItem: &type];
			[data addItems: &tmp
			[data addItems: &tmp count: sizeof(tmp)];
				 count: sizeof(tmp)];
		} else if (value <= UINT64_MAX) {
			uint8_t type = 0xCF;
			uint64_t tmp = OF_BSWAP64_IF_LE((uint64_t)value);
			uint64_t tmp = OFToBigEndian64((uint64_t)value);

			data = [OFMutableData dataWithItemSize: 1
			data = [OFMutableData dataWithCapacity: 9];
						      capacity: 9];

			[data addItem: &type];
			[data addItems: &tmp
			[data addItems: &tmp count: sizeof(tmp)];
				 count: sizeof(tmp)];
		} else
			@throw [OFOutOfRangeException exception];
	} else
		@throw [OFInvalidFormatException exception];

	[data makeImmutable];

	return data;
}
@end