/* * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3.0 only, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * version 3.0 for more details. * * You should have received a copy of the GNU Lesser General Public License * version 3.0 along with this program. If not, see * . */ #include "config.h" #import "OFTaggedPointerNumber.h" #import "OFInvalidFormatException.h" enum Tag { tagChar, tagShort, tagInt, tagLong, tagLongLong, tagUnsignedChar, tagUnsignedShort, tagUnsignedInt, tagUnsignedLong, tagUnsignedLongLong, }; static const uintptr_t tagMask = (1 << OFTaggedPointerNumberTagBits) - 1; static int numberTag; @implementation OFTaggedPointerNumber + (void)initialize { if (self == [OFTaggedPointerNumber class]) numberTag = objc_registerTaggedPointerClass(self); } + (OFTaggedPointerNumber *)numberWithChar: (signed char)value { return objc_createTaggedPointer(numberTag, ((uintptr_t)(unsigned char)value << OFTaggedPointerNumberTagBits) | tagChar); } + (OFTaggedPointerNumber *)numberWithShort: (short)value { return objc_createTaggedPointer(numberTag, ((uintptr_t)(unsigned short)value << OFTaggedPointerNumberTagBits) | tagShort); } + (OFTaggedPointerNumber *)numberWithInt: (int)value { return objc_createTaggedPointer(numberTag, ((uintptr_t)(unsigned int)value << OFTaggedPointerNumberTagBits) | tagInt); } + (OFTaggedPointerNumber *)numberWithLong: (long)value { return objc_createTaggedPointer(numberTag, ((uintptr_t)(unsigned long)value << OFTaggedPointerNumberTagBits) | tagLong); } + (OFTaggedPointerNumber *)numberWithLongLong: (long long)value { return objc_createTaggedPointer(numberTag, ((uintptr_t)(unsigned long long)value << OFTaggedPointerNumberTagBits) | tagLongLong); } + (OFTaggedPointerNumber *)numberWithUnsignedChar: (unsigned char)value { return objc_createTaggedPointer(numberTag, ((uintptr_t)value << OFTaggedPointerNumberTagBits) | tagUnsignedChar); } + (OFTaggedPointerNumber *)numberWithUnsignedShort: (unsigned short)value { return objc_createTaggedPointer(numberTag, ((uintptr_t)value << OFTaggedPointerNumberTagBits) | tagUnsignedShort); } + (OFTaggedPointerNumber *)numberWithUnsignedInt: (unsigned int)value { return objc_createTaggedPointer(numberTag, ((uintptr_t)value << OFTaggedPointerNumberTagBits) | tagUnsignedInt); } + (OFTaggedPointerNumber *)numberWithUnsignedLong: (unsigned long)value { return objc_createTaggedPointer(numberTag, ((uintptr_t)value << OFTaggedPointerNumberTagBits) | tagUnsignedLong); } + (OFTaggedPointerNumber *)numberWithUnsignedLongLong: (unsigned long long)value { return objc_createTaggedPointer(numberTag, ((uintptr_t)value << OFTaggedPointerNumberTagBits) | tagUnsignedLongLong); } - (const char *)objCType { uintptr_t value = object_getTaggedPointerValue(self); switch (value & tagMask) { case tagChar: return @encode(signed char); case tagShort: return @encode(short); case tagInt: return @encode(int); case tagLong: return @encode(long); case tagLongLong: return @encode(long long); case tagUnsignedChar: return @encode(unsigned char); case tagUnsignedShort: return @encode(unsigned short); case tagUnsignedInt: return @encode(unsigned int); case tagUnsignedLong: return @encode(unsigned long); case tagUnsignedLongLong: return @encode(unsigned long long); default: @throw [OFInvalidFormatException exception]; } } #define RETURN_VALUE \ uintptr_t value = object_getTaggedPointerValue(self); \ \ switch (value & tagMask) { \ case tagChar: \ return (signed char)(unsigned char) \ (value >> OFTaggedPointerNumberTagBits); \ case tagShort: \ return (short)(unsigned short) \ (value >> OFTaggedPointerNumberTagBits); \ case tagInt: \ return (int)(unsigned int) \ (value >> OFTaggedPointerNumberTagBits); \ case tagLong: \ return (long)(unsigned long) \ (value >> OFTaggedPointerNumberTagBits); \ case tagLongLong: \ return (long long)(unsigned long long) \ (value >> OFTaggedPointerNumberTagBits); \ case tagUnsignedChar: \ return (unsigned char) \ (value >> OFTaggedPointerNumberTagBits); \ case tagUnsignedShort: \ return (unsigned short) \ (value >> OFTaggedPointerNumberTagBits); \ case tagUnsignedInt: \ return (unsigned int) \ (value >> OFTaggedPointerNumberTagBits); \ case tagUnsignedLong: \ return (unsigned long) \ (value >> OFTaggedPointerNumberTagBits); \ case tagUnsignedLongLong: \ return (unsigned long long) \ (value >> OFTaggedPointerNumberTagBits); \ default: \ @throw [OFInvalidFormatException exception]; \ } - (long long)longLongValue { RETURN_VALUE } - (unsigned long long)unsignedLongLongValue { RETURN_VALUE } - (double)doubleValue { RETURN_VALUE } #undef RETURN_VALUE OF_SINGLETON_METHODS @end