Giter VIP home page Giter VIP logo

jrenum's Introduction

JREnum

Original idea and implementation by Benedict Cohen.

JREnum is a macro that automates creation of functions that blast enums from boring primitive compile-time-land to the fun-filled party environment of runtime.

Let's use a concrete example. Instead of writing:

typedef enum {
    Stream_Disconnected,
    Stream_Connecting,
    Stream_Connected,
    Stream_Disconnecting
}   StreamState;

write:

JREnum(StreamState,
       Stream_Disconnected,
       Stream_Connecting,
       Stream_Connected,
       Stream_Disconnecting);

This will generate the previous typedef enum and will also generate a corresponding suite of functions:

NSString* StreamStateToString(int value)

Given a value, will return the enum's string representation. For example StreamStateToString(2) would return @"Stream_Connected".

When confronted with values not defined in the enumeration, this function will return a placeholder string explaining the situation. For example StreamStateToString(2000) would return @"<unknown StreamState: 2000>".

BOOL StreamStateFromString(NSString *enumLabel, StreamState *enumValue)

Attempts to return the enum's int value given its label. For example StreamStateFromString(@"Stream_Disconnecting", &value) would return YES and set value to 3.

This function returns NO if the label for the enum type is unknown. For example StreamStateFromString(@"lackadaisical", &value) would return NO and leave value untouched.

NSDictionary* StreamStateByValue()

Returns a dictionary whose keys are the enum's values. Used by StreamStateToString().

When enums have multiple overlapping values, the current implementation exhibits last-write-wins behavior.

NSDictionary* StreamStateByLabel()

Returns a dictionary whose keys are the enum's labels. Used by StreamStateFromString(). This is the function you want if you wish to enumerate an enum's labels and values at runtime.

Split Header / Source Files

JREnum() is fine for when you have an enum that lives solely in an .m file. But if you're exposing an enum in a header file, you'll have to use the alternate macros. In your .h, use JREnumDeclare():

JREnumDeclare(StreamState,
              Stream_Disconnected,
              Stream_Connecting,
              Stream_Connected,
              Stream_Disconnecting);

And then use JREnumDefine() in your .m:

JREnumDefine(StreamState);

Explicit Values

You can also explicitly define enum integer values:

JREnum(StreamState,
       Stream_Disconnected = 42,
       Stream_Connecting,
       Stream_Connected,
       Stream_Disconnecting);

In the above scenario, Stream_Disconnected's value will be 42, Stream_Connecting's will be 43 and so on.

You can also use hex values:

JREnum(StreamState,
       Stream_Disconnected = 0x2A,
       Stream_Connecting,
       Stream_Connected,
       Stream_Disconnecting);

That's semantically identical to the above.

New in v1.1 you can use very simple bit-shift masks:

JREnum(Align,
	   AlignLeft         = 1 << 0,
	   AlignRight        = 1 << 1,
	   AlignTop          = 1 << 2,
	   AlignBottom       = 1 << 3,
	   AlignTopLeft      = 0x05,
	   AlignBottomLeft   = 0x09,
	   AlignTopRight     = 0x06,
	   AlignBottomRight  = 0x0A,
	   );

This helps where you want one variable to house a combination of flags:

Align botRight 		  = AlignBottomRight;
Align botRightBitWise = AlignBottom | AlignRight;

NSLog(@"Are They The Same: %@", (botRightBitWise == botRight) ? @"YES" : @"NO");
//=> Are They The Same: YES

But better, because you can go to-and-fro string values:

NSLog(@"How is that combo aligned? %@", AlignToString(botRightBitWise));
//=> How is that combo aligned? AlignBottomRight

TODO

Version History

v1.2: Jul 4 2017

v1.1: Mar 25 2014

  • [NEW] Add support for hex constants. (Alex Gray)
  • [NEW] Add support for very simple bit-shifting constants. (rentzsch)

v1.0.1: May 28 2013

v1.0: Apr 09 2013

  • Minor bug fix from 0.2.

v0.2: Dec 10 2012

  • [NEW] Generalized to support bidirectional enum label/value lookup and full runtime access to lookup dictionary.
  • [NEW] Add passing tests.
  • [NEW] Write this README.

v0.1: Dec 9 2012

  • [NEW] Devised way to allow split declaration/definition macros to allow use in header/source files.

Prelude: Dec 8 2012

jrenum's People

Contributors

insanehunter avatar maniak-dobrii avatar mralexgray avatar rentzsch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

jrenum's Issues

Linker Error: Duplicate Symbols.

ld: 50 duplicate symbols for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)

JREnumDeclare causing compiler "Unused variable" warnings.

… Unused variable '_AZQuadrant_constants_string'

i tried wrapping the whole macro in

`#pragma clang diagnostic push

pragma clang diagnostic ignored "-Wunused-value"

"JREnumDeclare…"

pragma clang diagnostic pop`

or just wrapping the

static NSString *_##ENUM_TYPENAME##_constants_string = @"" #ENUM_CONSTANTS;

line, but didn't help. actually, tried wrapping the single line with the weird `_Pragma( blah blah blah) format - that "supposedly" works with Macros.

I finally tied to just convert the whole thing to a straight function… but i can't figure out what the hell ##ByValue(); etc are doing.

any advice?

Generate string conversion methods from existent NS_ENUM declarations

e.g. Looking at UIImagePickerController, I want to benefit from printing out strings that correspond to the values of UIImagePickerControllerSourceType, or UIImagePickerControllerQualityType for example.

Since it's already been declared in UIKit it's unclear to me how JREnum could inspect such a declaration and generate convertors.

Xcode 9 gives zillions of errors

When I use the latest Xcode 9 beta, I get errors like

/GameConstants.h:31:1: warning: this function declaration is not a prototype [-Wstrict-prototypes]
JREnumDeclare(AttitudeColor,
^
In file included from GameConstants.h:15:
Utilities/JREnum.h:30:48: note: expanded from macro 'JREnumDeclare'
extern NSDictionary* ENUM_TYPENAME##ByValue(); \

Is this something that can be addressed in the macros?

Xcode 11 issues warnings for JREnumDefine

I get the error

Converting a pointer value of type 'NSNumber *' to a primitive boolean value; instead, either compare the pointer to nil or call -boolValue

Fix is

diff --git a/Source/Utilities/JREnum.h b/Source/Utilities/JREnum.h
index 48d5028cb..d748fb13d 100755
--- a/Source/Utilities/JREnum.h
+++ b/Source/Utilities/JREnum.h
@@ -110,7 +110,7 @@
         \
     BOOL ENUM_TYPENAME##FromString(NSString *enumLabel, ENUM_TYPENAME *enumValue) {    \
         NSNumber *value = [ENUM_TYPENAME##ByLabel() objectForKey:enumLabel];   \
-        if (value) {   \
+        if ([value boolValue]) {    \
             *enumValue = (ENUM_TYPENAME)[value intValue];      \
             return YES;        \
         } else {       \

(Yes, I know there is such a thing as a pull request, but I have no idea how that works.)

Podspec outdated

The current podspec on CocoaPods for JREnum still points to version 0.2.

Tests don't work without use in main build

I installed this library from Cocoapods, and I'm coming across a strange error. When writing my tests, I come across a compile error detailing that the private methods (starting with '_') don't exist for arm64, which is likely just because it's the compile platform. The error shows up within the actual test itself.

In my project, I'm calling JREnumDeclare in the .h and JREnumDefine in the .m.

However, I wanted to see if it was only the test platform that was causing the error, and it was. When I defined a "test" in my main project file, it ran fine, even when called from a test case.

Finally, I removed the call to that "test" method in my main project, reimplemented the code that was causing the error, and ran again, and it still worked. Removing the method in my main project, however, even though it wasn't being called, caused the error to reassert itself.

This is the error I receive

Undefined symbols for architecture arm64:
  "_SDLEJREnumResultFromString", referenced from:
      -[SDLEStringEnumTests testSlowStringToEnum] in SDLEStringEnumTests.o
  "_SDLEJREnumResultToString", referenced from:
      -[SDLEStringEnumTests testSlowEnumToString] in SDLEStringEnumTests.o

based on this code:

- (void)testSlowEnumToString
{
    NSString *SUCCESSString = @"JRSUCCESS";

    XCTAssert([SDLEJREnumResultToString(JRSUCCESS) isEqualToString:SUCCESSString], @"Did not properly convert JREnum to String");
}

- (void)testSlowStringToEnum
{
    SDLEJREnumResult someEnumResult = JRSUCCESS;
    NSString *someMatchingEnumResultString = @"JRSuccess";
    SDLEJREnumResult value;

    SDLEJREnumResultFromString(someMatchingEnumResultString, &value);

    XCTAssertEqual(value, someEnumResult, @"Did not properly convert String to JREnum");
}

When this method exists in my main project, it works

+ (void)testSlow
{
    SDLEJREnumResult testEnum;
    NSString *testStr = SDLEJREnumResultToString(JRSUCCESS);
    SDLEJREnumResultFromString(@"JRSUCCESS", &testEnum);

    NSLog(@"Test Str: %@\n"
          "Enum: %u", testStr, testEnum);
}

and when it's removed or commented out, it causes the error above.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.