brian.clear
brian.clear

Reputation: 5327

Objective-C typedef enum - two enums maps to same values

I've taken over a project and it uses an enum to flag API calls.

It can filter them by OR'ing the enum values so a previous developer did some bitshifting.

typedef enum {
APICallTimeSeriesSearchTimeSeries   = (1LL << 1),
APICallTimeSeriesGetTimeSeriesInfo  = (1LL << 2),
APICallTimeSeriesGetSeriesInfo      = (1LL << 3),
....
APICallFavouritesAddNewsFavourite               = (1LL << 79),
APICallFavouritesRemoveNewsFavourite            = (1LL << 80),
APICallFavouritesGetAllFavourites               = (1LL << 81)
} APICallType;

Then we can do things like

filter(APICallTimeSeriesGetTimeSeriesInfo | APICallTimeSeriesGetSeriesInfo | APICallTimeSeriesGetSeriesData);

But recently I notice similar enums mapped to the same value. I dumped the whole enum list like so

NSLog(@"%d",APICallTimeSeriesSearchTimeSeries);
NSLog(@"%d",APICallTimeSeriesGetTimeSeriesInfo);
NSLog(@"%d",APICallTimeSeriesGetSeriesInfo);
NSLog(@"%d",APICallTimeSeriesGetSeriesData);
NSLog(@"%d",APICallFleetSearchVessels);
NSLog(@"%d",APICallFleetGetVesselInfo);
etc.

And we can see the bitshifting in action

2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
131072
262144
524288
1048576
2097152
4194304
8388608
16777216
33554432
67108864
134217728
268435456
536870912
1073741824
2147483648
4294967296
8589934592
17179869184
34359738368
68719476736

The problem is after (1LL << 63) the same values are generated

1152921504606846976 APICallFavouritesAddMarketFavourite = (1LL << 60)
2305843009213693952 APICallFavouritesRemoveMarketFavourite  = (1LL << 61)
4611686018427387904 APICallFavouritesGetFutureFavourites    = (1LL << 62)
-9223372036854775808    APICallFavouritesAddFutureFavourite = (1LL << 63)
-9223372036854775808    APICallFavouritesRemoveFutureFavourite  = (1LL << 64)
-9223372036854775808    APICallFavouritesRemoveVesselFavourite  = (1LL << 65)

etc same value(-9223372036854775808) repeats for all new enums

From this thread Types in objective-c on iPhone

its because -9223372036854775808 is LLONG_MIN

NSLog(@"LLONG_MIN:  %lli", LLONG_MIN);   // signed long long int

I noticed theres a higher value

NSLog(@"LLONG_MAX:  %lli", LLONG_MAX);
NSLog(@"ULLONG_MAX: %llu", ULLONG_MAX);  // unsigned long long int

LLONG_MIN:  -9223372036854775808         
LLONG_MAX:  9223372036854775807          
ULLONG_MAX: 18446744073709551615 

but cant find ULLONG_MIN

How do we fix this?

I tried changing the primitive storage from 1LL to 1ULL but no effect.

FROM:

typedef enum {
APICallTimeSeriesSearchTimeSeries   = (1LL << 1),
APICallTimeSeriesGetTimeSeriesInfo  = (1LL << 2),
APICallTimeSeriesGetSeriesInfo      = (1LL << 3),
...

TO:

typedef enum {
APICallTimeSeriesSearchTimeSeries               = (1ULL << 1),
APICallTimeSeriesGetTimeSeriesInfo              = (1ULL << 2),
APICallTimeSeriesGetSeriesInfo                  = (1ULL << 3),
...

cheers

Upvotes: 0

Views: 913

Answers (2)

brian.clear
brian.clear

Reputation: 5327

I chose to split the APICallType into another enum. It was that or rewire a 3 year old projects and have to test every API call.

APICallTimeSeriesSearchTimeSeries   = (1LL << 1),
APICallTimeSeriesGetTimeSeriesInfo  = (1LL << 2),
APICallTimeSeriesGetSeriesInfo      = (1LL << 3),
....
APICallFavouritesAddNewsFavourite               = (1LL << 79),
APICallFavouritesRemoveNewsFavourite            = (1LL << 80),
APICallFavouritesGetAllFavourites               = (1LL << 81)
} APICallType;

CHANGED TO

typedef enum {
APICallTimeSeriesSearchTimeSeries   = (1LL << 1),
APICallTimeSeriesGetTimeSeriesInfo  = (1LL << 2),
APICallTimeSeriesGetSeriesInfo      = (1LL << 3),
APICallTimeSeriesGetSeriesData      = (1LL << 4),
APICallFleetSearchVessels           = (1LL << 5),
APICallFleetGetVesselInfo           = (1LL << 6),
APICallNewsGetNewsItems             = (1LL << 7),
APICallNewsGetPublicationItems      = (1LL << 8),
APICallPodcastGetPodcastItems       = (1LL << 9),
APICallUserLoginAuthenticateUser    = (1LL << 10),
APICallFFASearchFFARoutes           = (1LL << 11),
APICallFFAGetRouteData              = (1LL << 12),
APICallOwnerSearchOwners            = (1LL << 13),
APICallOwnerGetOwnerFleet           = (1LL << 14),
APICallIndicesSearchIndices         = (1LL << 15),
APICallIndicesGetIndicesData        = (1LL << 16),
APICallEquitiesGetEquitiesData      = (1LL << 17),
APICallEquitiesGetEquityPreviews    = (1LL << 18),
APICallEquitiesSearchBrokingStocks  = (1LL << 19),
APICallEquitiesSearchIndices        = (1LL << 20),
APICallEquitiesSearchCurrencies     = (1LL << 21),
APICallEquitiesGetRelatedNewsItems  = (1LL << 22),
APICallEquitiesGetCurrencyList      = (1LL << 23),
APICallSandPVesselsSearch           = (1LL << 24),
APICallSandPVesselSalesSearch       = (1LL << 25),
APICallSandPGetCommercialData       = (1LL << 26),
APICallSandPGetSimilarSales         = (1LL << 27),
APICallSandPGetFullVesselDetails    = (1LL << 28),
APICallSandPEnquiriesSearch         = (1LL << 29),
APICallTimeSeriesGetCategories                  = (1LL << 30),
APICallTimeSeriesGetShipTypes                   = (1LL << 31),
APICallTimeSeriesGetDataTypes                   = (1LL << 32),
APICallTimeSeriesSearchTimeSeriesWithCategories = (1LL << 33),
APICallHomeGetComments                          = (1LL << 34),
APICallEquitiesGetRelatedNewsItemsWithIds       = (1LL << 35),
APICallEquitiesSearchEquitiesBrokingStocks      = (1LL << 36),
APICallTimeSeriesGetFutureShipTypes             = (1LL << 37),
APICallTimeSeriesGetFutureDataTypes             = (1LL << 38),
APICallTimeSeriesGetOHLCData                    = (1LL << 39),
APICallTimeSeriesGetSeriesDataMaxPoints         = (1LL << 40),
APICallTimeSeriesGetSeriesOHLCDataMaxPoints     = (1LL << 41),
APICallClientSearchClients                      = (1LL << 42),
APICallClientGetClientListForBroker             = (1LL << 43),
APICallClientSearchDivisionsAndDesks            = (1LL << 44),
APICallClientGetDivisionsAndDesks               = (1LL << 45),
APICallClientSaveEmployeeDetails                = (1LL << 46),
APICallTimeSeriesSearchWithSeriesId             = (1LL << 47),
APICallHomeGetCommentsCargo                     = (1LL << 48),
APICallHomeGetCommentsSandP                     = (1LL << 49),
APICallHomeGetCommentsTanker                    = (1LL << 50),
APICallClientGetSandPRoutes                     = (1LL << 51),
APICallClientGetSandP2ndHandValues              = (1LL << 52),
APICallHomeGetCommentsSpecialised               = (1LL << 53),
APICallClientGetSpecialised                     = (1LL << 54),
APICallClientGetGas                             = (1LL << 55),
APICallClientGetGasBunkerPrices                 = (1LL << 56),
APICallFFAGetAllWhiteboardSpreadTypes           = (1LL << 57),
APICallFFAGetWhiteboardSpreadPricesForType      = (1LL << 58),
APICallFavourites                               = (1LL << 59)
/*
APICallFavouritesGetMarketFavourites            = (1LL << 59),
APICallFavouritesAddMarketFavourite             = (1LL << 60),
APICallFavouritesRemoveMarketFavourite          = (1LL << 61),
APICallFavouritesGetFutureFavourites            = (1LL << 62),

//Enum bit shifted greater than 63 will have same value as MAX INT reached
//moved these to 
APICallFavouritesAddFutureFavourite             = (1LL << 63),
APICallFavouritesRemoveFutureFavourite          = (1LL << 64),
APICallFavouritesGetVesselOwnerFavourites       = (1LL << 65),
APICallFavouritesGetVesselFavourites            = (1LL << 66),
APICallFavouritesAddVesselFavourite             = (1LL << 67),
APICallFavouritesRemoveVesselFavourite          = (1LL << 68),
APICallFavouritesGetOwnerFavourites             = (1LL << 69),
APICallFavouritesAddOwnerFavourite              = (1LL << 70),
APICallFavouritesRemoveOwnerFavourite           = (1LL << 71),
APICallFavouritesGetShippingStockFavourites     = (1LL << 72),
APICallFavouritesAddShippingStockFavourite      = (1LL << 73),
APICallFavouritesRemoveShippingStockFavourite   = (1LL << 74),
APICallFavouritesGetIndicieFavourites           = (1LL << 75),
APICallFavouritesAddIndicieFavourite            = (1LL << 76),
APICallFavouritesRemoveIndicieFavourite         = (1LL << 77),
APICallFavouritesGetNewsFavourites              = (1LL << 78),
APICallFavouritesAddNewsFavourite               = (1LL << 79),
APICallFavouritesRemoveNewsFavourite            = (1LL << 80),
APICallFavouritesGetAllFavourites               = (1LL << 81)
*/

} APICallType;

AND ADDED APICallSubType

typedef enum {

/* for use with APICallType:APICallFavourites */
APICallFavouritesGetMarketFavourites            = (1LL << 1),
APICallFavouritesAddMarketFavourite             = (1LL << 2),
APICallFavouritesRemoveMarketFavourite          = (1LL << 3),

APICallFavouritesGetFutureFavourites            = (1LL << 4),
APICallFavouritesAddFutureFavourite             = (1LL << 5),
APICallFavouritesRemoveFutureFavourite          = (1LL << 6),

APICallFavouritesGetVesselOwnerFavourites       = (1LL << 7),
APICallFavouritesGetVesselFavourites            = (1LL << 8),
APICallFavouritesAddVesselFavourite             = (1LL << 9),
APICallFavouritesRemoveVesselFavourite          = (1LL << 10),

APICallFavouritesGetOwnerFavourites             = (1LL << 11),
APICallFavouritesAddOwnerFavourite              = (1LL << 12),
APICallFavouritesRemoveOwnerFavourite           = (1LL << 13),

APICallFavouritesGetShippingStockFavourites     = (1LL << 14),
APICallFavouritesAddShippingStockFavourite      = (1LL << 15),
APICallFavouritesRemoveShippingStockFavourite   = (1LL << 16),

APICallFavouritesGetIndicieFavourites           = (1LL << 17),
APICallFavouritesAddIndicieFavourite            = (1LL << 18),
APICallFavouritesRemoveIndicieFavourite         = (1LL << 19),

APICallFavouritesGetNewsFavourites              = (1LL << 20),
APICallFavouritesAddNewsFavourite               = (1LL << 21),
APICallFavouritesRemoveNewsFavourite            = (1LL << 22),
APICallFavouritesGetAllFavourites               = (1LL << 23)
//do not go over (1LL << 63) - enum values start at MAX INT after that

} APICallSubType;

AND ANYWHERE I CHECKED the type I had to afterwards check the subtype

filter(APICallFavourites);
filterSubType(APICallFavouritesAddVesselFavourite |
              APICallFavouritesRemoveVesselFavourite);

if (responseOfSubType(APICallFavouritesAddVesselFavourite))
{
    NSLog(@"%s APICallFavouritesAddVesselFavourite response not handled", __PRETTY_FUNCTION__);
}

if (responseOfSubType(APICallFavouritesRemoveVesselFavourite))
{
    NSLog(@"%s APICallFavouritesRemoveVesselFavourite response not handled", __PRETTY_FUNCTION__);
}

Upvotes: 0

Fredrik Johansson
Fredrik Johansson

Reputation: 1301

ULLONG_MIN is 0. ULLONG means unsigned long long, i.e. a positive value represented by 64 bits.

If you want positive and negative numbers you can only represent half of that set of values that you can represent by an unsigned type of the same bit width. That's the reason that the ULLONG_MAX is bigger.

Upvotes: 1

Related Questions