Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haxe - sending enum as flags to a function

I'm just trying to convert my code from C# to Haxe NME. I use enums as flags.

[Flags]
enum State
{
    StateOne    = 1,
    StateTwo    = 2,
    StateThree  = 4
}

And use it

if (someObj.HasState(State.StateOne | State.StateTwo))
{
    // Contains both the states. Do something now.
}

I had no idea on how to do this in Haxe NME.

Thanks.

like image 865
Sri Harsha Chilakapati Avatar asked May 16 '13 06:05

Sri Harsha Chilakapati


2 Answers

In Haxe 3, there is haxe.EnumFlags. This uses Haxe 3 Abstract Types which basically wrap an underlying type, in this case, it uses an Int, just like you have done - but then it wraps it up in a pretty API so you don't have to worry about the details.

Here is some sample code:

import haxe.EnumFlags;

class EnumFlagTest 
{
    static function main()
    {
        var flags = new EnumFlags<State>();
        flags.set(StateOne);
        flags.set(StateTwo);
        flags.set(StateThree);
        flags.unset(StateTwo);

        if (flags.has(StateOne)) trace ("State One active");
        if (flags.has(StateTwo)) trace ("State Two active");
        if (flags.has(StateThree)) trace ("State Three active");

        if (flags.has(StateOne) && flags.has(StateTwo)) trace ("One and Two both active");
        if (flags.has(StateOne) && flags.has(StateThree)) trace ("One and Three both active");
    }
}

enum State
{
    StateOne;
    StateTwo;
    StateThree;
}

All of this works is stored as a standard Int, and uses integer operators like you have done, so it should be pretty fast (no wrapping in an external object). If you want to see how it works under the box, the source code for EnumFlags can be viewed here.

If you're still on Haxe 2, then you could create an object that is really similar, but of course, it has to create an object as well as the integer, so if you're doing thousands (millions?) of them then you might get a slow down. The equivalent code, that should work with Haxe 2 (though I haven't checked):

class MyEnumFlags<T:EnumValue>
{
    var i:Int;

    public function new(?i=0)
    {
        this.i = i;
    }

    public inline function has( v : T ) : Bool {
        return i & (1 << Type.enumIndex(v)) != 0;
    }

    public inline function set( v : T ) : Void {
        i |= 1 << Type.enumIndex(v);
    }

    public inline function unset( v : T ) : Void {
        i &= 0xFFFFFFF - (1 << Type.enumIndex(v));
    }

    public inline static function ofInt<T:EnumValue>( i : Int ) : MyEnumFlags<T> {
        return new MyEnumFlags<T>(i);
    }

    public inline function toInt() : Int {
        return i;
    }
}
like image 83
Jason O'Neil Avatar answered Oct 01 '22 13:10

Jason O'Neil


I've managed to find it. I had trouble using enums but I had been successful using constants. This is the simple test file I used.

package ;

class FlagsTest
{

    static inline var FLG_1:Int = 1;
    static inline var FLG_2:Int = 2;

    public static function main() : Void
    {
        var flag:Int = FLG_1;
        if (hasFlag(flag, FLG_1))
        {
            trace ("Test 1 passed");
        }
        flag |= FLG_2;
        if (hasFlag(flag, FLG_2))
        {
            trace ("Test 2 passed");
        }
    }

    public static function hasFlag( flags:Int, flag:Int ) : Bool
    {
        return ((flags & flag) == flag) ? true : false;
    }

}

Output:

FlagsTest.hx line 14: Test 1 passed
FlagsTest.hx line 19: Test 2 passed
like image 25
Sri Harsha Chilakapati Avatar answered Oct 01 '22 13:10

Sri Harsha Chilakapati