1

Note: I'm not sure how best to title and tag this question so helpful edits welcome!

I am reverse engineering an ASP.NET Webforms website (for which I don't have the correct version of the source code) to ASP.NET MVC using database first entity framework, and am having difficulty understanding how a particular view/set of data works.

A record has an "Options" field which contains a series of numbers which, when read, identify which of 48 options are true. I'm trying to figure out how to read/write this result.

So, the options table is structured like so: enter image description here As you can see there is a BitValue column (Which continues up to 281474976710656); I believe this is what I need to use to identify the options when presented with a number like so: 5120 or 17592186044480 If that number only identified a single option I'd probably be able to figure this out easier but unfortunately there can be several options identified.

So for example, a record has this in it's options field: 17592186044480 The options this identifies (when I refer to the existing website) are: Procedure (BitValue: 64) Shore Crew Error (BitValue: 17592186044416)

But I can't for the life of me figure out how both of those numbers translate to the one in the options field!

Any hints?

Ok, so 64 + 17592186044416 = 17592186044480 That helps understand how the number is generated, but how to I reverse this to identify the options that make up the number?

CONCLUSION I have accepted an answer as, in combination with some comments, it helped me find the solution.

In the end, I wrote out the "options" as an enum like so...

[Flags] public enum options : long
{
    Master_Pilot_Exchange = 2,
    Bridge_Team_Issues = 4,
    Language_Difficulty = 8,
    Briefing = 16,
    Crew_Competency = 32,
    Procedure = 64,
    Personal_Performance = 128,
    Fatigue = 256,
    ....
}

and created a function to check each option to see if it is included in the bitValue:

private bool checkBits(long maskIn, int optionId)
    {
        options mask = (options)maskIn;
        var toCheck = db.InitialReportOptions.Single(i => i.InitialReportOptionID == optionId);
        options chk = (options)toCheck.BitValue;
        bool test = false;
        if ((mask & chk) == chk)
        {
            test = true;
        }
        //
        return test;
    }

And when I need to add a new bitValue to a record, I use the following:

options newMask = (options)0;
            long bitResult = 0;
            foreach(var option in model.ReportOptions)
            {
                if (option.IsTrue)
                {
                    var bitv = (options)option.BitValue;
                    bitResult = bitResult | ( (long)newMask | (long)bitv);
                }
            }
            model.InitialReportRecord.Options = bitResult;

I daresay it could be more efficient but it works so I'm happy!

Ego Placebo
  • 157
  • 2
  • 14
  • `64 + 17592186044416 = 17592186044480` –  Dec 20 '17 at 04:05
  • Ah I see, thanks @StephenMuecke: that helps identify how the number is generated, but how do I reverse that in order to get 64 & 17592186044416 from 17592186044480 without knowing in advance what went into it? – Ego Placebo Dec 20 '17 at 04:08
  • Are you using a enum with the `[Flags]` attribute for this? –  Dec 20 '17 at 04:10
  • All I have at this stage is the data itself, since I don't know how to start deciphering it! I've never used the Flags attribute so I guess I'll see if I can figure out how that might help me lol – Ego Placebo Dec 20 '17 at 04:12
  • I would have thought you convert it to binary and read the bits as flags For example 19 = 10011, which would be options 0, 1 and 4. 17592186044480 = ‭000100000000000000000000000000000000000001000000‬, gives you a flags 68 and 6 I think – Alan Dec 20 '17 at 04:18
  • It might be easier using a [FlagsAttribute](https://msdn.microsoft.com/en-us/library/system.flagsattribute(v=vs.110).aspx) on an enum, but you can use bitwise operators. Refer [this answer](https://stackoverflow.com/questions/14479981/how-do-i-check-if-bitmask-contains-bit) for some examples –  Dec 20 '17 at 04:22
  • Hmm OK thanks guys, this is all very new to me; I've never worked with binary like that or bitwise operators and such, I'll refer to those examples and see if I can figure it out, wish me luck! – Ego Placebo Dec 20 '17 at 04:27
  • Not sure how you currently working with this in the view, but [this answer](https://stackoverflow.com/questions/37990786/how-to-reduce-code-duplication-in-asp-net-mvc-view-when-working-with-flags-enum/37991402#37991402) might help. –  Dec 20 '17 at 04:36

1 Answers1

2

Firstly you need to know the bit values for each of the 48 flags.... Then in C# ...

const int Procedure = 64

if ((myData.InitialReportOption & Procedure) == Procedure)
   // Then Procedure flag is active
else  // (myData.InitialReportOption & Procedure) == 0
   // Procedure is not active

Likewise to enable you would do...

myData.InitialReportOption |= Procedure;

and to disable

myData.InitialReportOption &= ~Procedure;

For more info try this blog...

http://blog.typps.com/2007/10/bitwise-operators-in-c-or-xor-and-not.html

Mick
  • 6,527
  • 4
  • 52
  • 67