Simpler way to do this?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • inexion

    Simpler way to do this?

    Hello,

    I'm sure theres a way to make this simpler but I haven't been able to
    figure it out.....heres whats going on:

    $tnum = array();
    for($i = 0; $i < count($targets['id']); $i++)
    {
    $tnum[] = hexdec($targets['flags'][$i]);
    $headr = substr(sprintf( '%032b', $tnum[$i]), 0, -12);
    $footr = substr(sprintf( '%012b', $tnum[$i]), -12);
    $fparts = str_split($binC ode, 3);
    $hparts = str_split($head r, 4);
    echo "{$hparts[0]}-{$hparts[1]}-{$hparts[2]}-{$hparts[3]}-
    {$hparts[4]}-";
    echo "{$fparts[0]}-{$fparts[1]}-{$fparts[2]}-{$fparts[3]}<br />";
    }

    Basically, I'm taking these records out of sql, decoding one of the
    columns that has hex values, into binary pieces that match a
    particular flag. Right now as an example, for "fparts" I'm just using
    4 seperate Switch statements for example....here is one of four:

    switch ($fparts[0])
    {
    case '001':
    echo "value1 <br />";
    break;
    case '010':
    echo "value2 <br />";
    break;
    case '011':
    echo "value3 <br />";
    break;
    case '100':
    echo "value4 <br />";
    break;
    case '101':
    echo "value5 <br />";
    break;
    case '110':
    echo "value6 <br />";
    break;
    default:
    echo "NO DATA <br />";
    }

    So each value1-6 is something I need returned and placed into a new
    sql column etc.. The echo's above can be replaced with a sql query
    and so on, my problem is that I'm sure theres an easier way to do this
    without using a hundred plus lines of code for 9 different switch
    statements. For instance maybe using logic operators to match the
    flags(?) Any help would be much appreciated, thanks!
  • Matija Papec

    #2
    Re: Simpler way to do this?

    inexion wrote:
    switch ($fparts[0])
    {
    case '001':
    echo "value1 <br />";
    break;
    case '010':
    echo "value2 <br />";
    break;
    case '011':
    echo "value3 <br />";
    break;
    case '100':
    echo "value4 <br />";
    break;
    case '101':
    echo "value5 <br />";
    break;
    case '110':
    echo "value6 <br />";
    break;
    default:
    echo "NO DATA <br />";
    }
    Use array instead of switch,
    $arr = array(
    "001" ="value 1",
    // ...
    );
    print isset($arr[$fparts[0]]) ? $arr[$fparts[0]] : "NO DATA";

    So each value1-6 is something I need returned and placed into a new
    sql column etc.. The echo's above can be replaced with a sql query
    and so on, my problem is that I'm sure theres an easier way to do this
    without using a hundred plus lines of code for 9 different switch
    statements. For instance maybe using logic operators to match the
    flags(?) Any help would be much appreciated, thanks!

    Comment

    • Michael Fesser

      #3
      Re: Simpler way to do this?

      ..oO(Matija Papec)
      >inexion wrote:
      >
      > switch ($fparts[0])
      > {
      > case '001':
      > echo "value1 <br />";
      > break;
      > case '010':
      > echo "value2 <br />";
      > break;
      > case '011':
      > echo "value3 <br />";
      > break;
      > case '100':
      > echo "value4 <br />";
      > break;
      > case '101':
      > echo "value5 <br />";
      > break;
      > case '110':
      > echo "value6 <br />";
      > break;
      > default:
      > echo "NO DATA <br />";
      > }
      >
      >Use array instead of switch,
      >$arr = array(
      "001" ="value 1",
      // ...
      >);
      >print isset($arr[$fparts[0]]) ? $arr[$fparts[0]] : "NO DATA";
      bindec() might be another option, dependent on what the OP wants to do.

      Micha

      Comment

      • inexion

        #4
        Re: Simpler way to do this?

        Thanks for the suggestions, I think I need to explain a little more
        about what I need in the if statement.....

        for example:

        Flags column
        ------------

        0x00201209


        so in binary, this field is being broken up like so:

        000000000010000 00001 001 000 001 001

        The 4 sets of bits at the beginning here can be ignored, I'm concerned
        with the 20 bits that remain. Is there a way I could create a mask or
        using logic be able to check whether a particular bit has been set in
        that field?

        In theory, the flags column could carry a set like.....0x0020 0209, or
        0x00812209, I need to use wildcards or something to identify if for
        instance the 8 has been set at that position, without having to make
        an array of all the possible combinations the field could have......

        hopefully thats possible, thanks again!

        Comment

        • Michael Fesser

          #5
          Re: Simpler way to do this?

          ..oO(inexion)
          >Thanks for the suggestions, I think I need to explain a little more
          >about what I need in the if statement.....
          >
          >for example:
          >
          >Flags column
          >------------
          >
          >0x00201209
          >
          >
          >so in binary, this field is being broken up like so:
          >
          >00000000001000 000001 001 000 001 001
          >
          >The 4 sets of bits at the beginning here can be ignored, I'm concerned
          >with the 20 bits that remain. Is there a way I could create a mask or
          >using logic be able to check whether a particular bit has been set in
          >that field?
          Checking if a bit is set is done with a logical AND:

          if (($flags & BIT_VALUE) == BIT_VALUE) {
          ...
          }

          The shorter variant:

          if ($flags & BIT_VALUE) {
          ...
          }

          will also work in this case, but doesn't return a boolean value and may
          cause problems if you want to test for multiple bits at the same time.
          >In theory, the flags column could carry a set like.....0x0020 0209, or
          >0x00812209, I need to use wildcards or something to identify if for
          >instance the 8 has been set at that position
          Do you mean the 8th bit?
          >without having to make
          >an array of all the possible combinations the field could have......
          Define a meaningful constant for each bit, then use the logical AND
          as shown above. IMHO it helps a lot to define such constants with hex
          values (the decimal values are just shown for completeness):

          define('BIT_1', 0x0001); // 2^0 = 1
          define('BIT_2', 0x0002); // 2^1 = 2
          define('BIT_3', 0x0004); // 2^2 = 4
          define('BIT_4', 0x0008); // 2^3 = 8
          define('BIT_5', 0x0010); // 2^4 = 16
          define('BIT_6', 0x0020); // 2^5 = 32
          define('BIT_7', 0x0040); // 2^6 = 64
          define('BIT_8', 0x0080); // 2^7 = 128
          ....

          Of course you should choose better names which represent the meaning of
          the flags.

          HTH
          Micha

          Comment

          • inexion

            #6
            Re: Simpler way to do this?

            Hey Micha,

            Thanks a lot for all your help so far Micha, much appreciated!

            The 8 in my example wasn't the eighth bit, but whatever place it was
            in up there (6th bit i think)....but your idea is perfect and would
            work just the same obviously.

            So in your example, I would just need to define a bunch more of the
            bits and use the bitwise logical AND in the if statement.

            for example...

            define('BIT_5', 0x00010); // 2^4 = 16
            define('BIT_6', 0x00020); // 2^5 = 32
            define('BIT_7', 0x00040); // 2^6 = 64
            define('BIT_8', 0x00080); // 2^7 = 128

            Here would be an if statement checking the fifth bit then....

            if(($fparts[0] & BIT_5) == BIT_5){
            ....

            }

            This statement is just checking $fparts[0] to see if its 0x00010
            though(?), does this mean I need an if statement for each...0x00020,
            0x00040, and 0x00080? Is there a way do it all at once? Can I make a
            combined OR statement perhaps?


            Comment

            • Michael Fesser

              #7
              Re: Simpler way to do this?

              ..oO(inexion)
              >Hey Micha,
              >
              >Thanks a lot for all your help so far Micha, much appreciated!
              You're welcome.
              >The 8 in my example wasn't the eighth bit, but whatever place it was
              >in up there (6th bit i think)....but your idea is perfect and would
              >work just the same obviously.
              >
              >So in your example, I would just need to define a bunch more of the
              >bits and use the bitwise logical AND in the if statement.
              >
              >for example...
              >
              >define('BIT_5' , 0x00010); // 2^4 = 16
              >define('BIT_6' , 0x00020); // 2^5 = 32
              >define('BIT_7' , 0x00040); // 2^6 = 64
              >define('BIT_8' , 0x00080); // 2^7 = 128
              >
              >Here would be an if statement checking the fifth bit then....
              >
              >if(($fparts[0] & BIT_5) == BIT_5){
              >...
              >
              >}
              >
              >This statement is just checking $fparts[0] to see if its 0x00010
              >though(?)
              Correct. It will just check that particular bit, all others will be
              ignored.
              >does this mean I need an if statement for each...0x00020,
              >0x00040, and 0x00080? Is there a way do it all at once? Can I make a
              >combined OR statement perhaps?
              Exactly. You can test multiple bits at once by combining them with a
              logical OR. In this case it might be easier to use a little function to
              perform the test, something like

              function hasFlag($flags, $value) {
              return ($flags & $value) == $value;
              }

              Then you can do things like:

              if (hasFlag($fpart s[0], BIT_6|BIT_7|BIT _8)) {
              // all three bits set
              }

              If some particular bit combinations are used quite regularly, then it
              could make sense to define additional constants for such combinations,
              e.g.

              define(BIT_678, BIT_6|BIT_7|BIT _8);

              if (hasFlag($fpart s[0], BIT_678)) {
              // all three bits set
              }

              To give a better real-life example: In a login system with various user
              privileges there could be these bit constants to control the access to
              some parts of the site or to a database record for example:

              define('USER_AC CESS_READ', 0x0001);
              define('USER_AC CESS_WRITE', 0x0002);

              For convenience there could also be the combination of these both if you
              want to check that a user has full access:

              define('USER_AC CESS_RW', USER_ACCESS_REA D|USER_ACCESS_W RITE);
              // or shorter: define('USER_AC CESS_RW', 0x0003);

              There are a lot of useful things you can do with such bit manipulations.

              HTH
              Micha

              Comment

              • inexion

                #8
                Re: Simpler way to do this?

                Ok so, I'm having a slight problem here - it seems like something is
                offset somehow, I will show an example:


                Using this mask...

                define('TMONLY' , 0x00800);


                and this statement...

                if(($hparts[0] & TMONLY) == TMONLY){
                echo "THIS SHOULD BE TMONLY<br />";
                }



                Ok, so then when I run this code, things are being marked on the page
                "THIS SHOULD BE TMONLY" when that bit is obviously not set (for
                example 601209), what could be going on?

                I tried to break it down by creating a test page to make sure the
                correct bits are being fed into it....for example....

                <?PHP

                $test = hexdec(601209);

                $headr = substr(sprintf( '%032b', $test), 0, -12);

                echo $headr;

                ?>

                this outputs 0000 0000 0110 0000 0001 for the last 20 bits - as you
                can see, 8 is not set here, but its returning to me as if it were for
                some reason. This is happening only for the 1,2,4,6, and 8's that are
                set in that bit....i.e..

                in binary...any variation of that field where 8 is set should be
                setting it to true:

                0000 0000 1000 0000 0000
                0000 0000 1001 0000 0000
                0000 0000 1010 0000 0000
                0000 0000 1011 0000 0000

                0000 0000 1100 0000 0000
                0000 0000 1101 0000 0000
                0000 0000 1110 0000 0000
                0000 0000 1111 0000 0000

                So why would something like the following set it off?

                0000 0000 0010 0000 0000
                0000 0000 0110 0000 0000


                Sorry I'm just confused =/

                Comment

                • inexion

                  #9
                  Re: Simpler way to do this?

                  I fixed it, I think it has to do with the fact that I was comparing a
                  binary number against a hex number.....so I converted my binary number
                  back to hex and changed my mask to simple hex digits.....

                  eg.:


                  define('TMONLY' , 800);




                  $tnum[] = hexdec($targets['flags'][$i]);
                  $headr = substr(sprintf( '%032b', $tnum[$i]), 0, -12);
                  $footr = substr(sprintf( '%012b', $tnum[$i]), -12);
                  $fparts = str_split($foot r, 3);
                  $hparts = str_split($head r, 20);
                  $hval = base_convert($h parts[0], 2, 16);

                  if(($hval & TMONLY) == TMONLY){
                  echo "THIS SHOULD BE 2MASS ONLY<br />";
                  }

                  Comment

                  Working...