Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 9 of 9
  1. #1
    Regular Coder
    Join Date
    Aug 2004
    Location
    codegoboom@yahoo.com
    Posts
    999
    Thanks
    0
    Thanked 0 Times in 0 Posts

    MS combined constants: How do they do that?

    Interdependent props... Is this a programming technique documented somewhere, or a trade secret?
    For example, the buttons argument for the VBS MsgBox Function:
    The first group of values (0–5) describes the number and type of buttons displayed in the dialog box; the second group (16, 32, 48, 64) describes the icon style; the third group (0, 256, 512, 768) determines which button is the default; and the fourth group (0, 4096) determines the modality of the message box. When adding numbers to create a final value for the argument buttons, use only one number from each group.
    Wtf is going on in that black box?
    Last edited by codegoboom; 11-29-2004 at 08:43 AM. Reason: goof
    *this message will self destruct in n-seconds*

  • #2
    Regular Coder
    Join Date
    Dec 2003
    Posts
    367
    Thanks
    0
    Thanked 0 Times in 0 Posts
    They are using separate bits out of the number. It's called sometimes bitmasks or bitfields.

    For example, I have one byte and I want to store three properties in it: the first property has 3 choices, the second 4 choices and the third has 3.
    Since the first property has 3 options, 1 bit isn't enough (that's only 0 or 1, so two choices). With two bits I can store 4 options (00,01,10,11), so that's enough so the first two bits represent the first property. The second property has 4 options, so thats also 2 bits, so bits 3 and 4 represent the second property. The third property only needs to choices so 1 bit is enough, bit 5.
    The first two bits in binary represent 1 and two, so my first property is saved with 0,1 and two. Bits 3 and 4 represent 4 and 8 (remember, we are talking about powers of 2), so the choices are 0, 4, 8, 12 (4 + 8). The fifth bit represents 16, so we use 0 and 16. Then you can add these properties up and store them in one byte without having any conflicts between the properties, since every number will affect different bits.

    shmoove

  • #3
    Supreme Overlord Spookster's Avatar
    Join Date
    May 2002
    Location
    Marion, IA USA
    Posts
    6,278
    Thanks
    4
    Thanked 83 Times in 82 Posts
    It's called packing bits. You can pack 8 bits into a byte. If you are only working with boolean values this is very handy. We use that technique at work to pass values back and forth between various pieces of our software that are running on different unix and vxworks systems. It is useful for real time systems where you need things to be as fast as possible.

    As schmoove suggested you can use a bitmask to identify a specific bit or set of bits. You can pack values other than just boolean values. You just need to make sure that you keep track of which bits go where.
    Spookster
    CodingForums Supreme Overlord
    All Hail Spookster

  • #4
    Regular Coder
    Join Date
    Aug 2004
    Location
    codegoboom@yahoo.com
    Posts
    999
    Thanks
    0
    Thanked 0 Times in 0 Posts
    How very interesting... thanks.

    So how would you guys go about unpacking the "buttons" bitfield with a bitmask?

    I was trying imagine it in javascript , but uh... this is the only way I got it to work:
    Code:
    <body>
    <script type="text/javascript">
    function unpack(buttons)
    {
    	var
    		bits = buttons.toString(2).split(""),
    		n = bits.length,
    		nibble = 4,
    		dec = 0; 
    	buttons = [];
    	while(n--)
    	{
    		dec += +bits.shift() * Math.pow(2, n);
    		if(n % nibble)
    			continue;
    		buttons.push(dec >> n);
    		dec = 0;
    	}
    	switch(buttons.pop())
    	{
    		case 1:
    			alert("jsOKCancel");
    			break;
    		case 2:
    			alert("jsAbortRetryIgnore");
    			break;
    		case 3:
    			alert("jsYesNoCancel");
    			break;
    		case 4:
    			alert("jsYesNo");
    			break;
    		case 5:
    			alert("jsRetryCancel");
    			break;
    		default:
    			alert("jsOKOnly");
    	}
    	switch(buttons.pop())
    	{
    		case 1:
    			alert("jsCritical");
    			break;
    		case 2:
    			alert("jsQuestion");
    			break;
    		case 3:
    			alert("jsExclamation");
    			break;
    		case 4:
    			alert("jsInformation");
    			break;
    	}
    	switch(buttons.pop())
    	{
    		case 1:
    			alert("jsDefaultButton2");
    			break;
    		case 2:
    			alert("jsDefaultButton3");
    			break;
    		case 3:
    			alert("jsDefaultButton4");
    			break;
    		default:
    			alert("jsDefaultButton1");
    	}
    	switch(buttons.pop())
    	{
    		case 1:
    			alert("jsSystemModal");
    			break;
    		default:
    			alert("jsApplicationModal");
    	}
    }
    </script>
    <form>
    <fieldset>
    <legend>Pack</legend>
    <label>Group 1: </label>
    	<select name="G1">
    		<option value="0"selected>jsOKOnly</option>
    		<option value="1">jsOKCancel</option>
    		<option value="2">jsAbortRetryIgnore</option>
    		<option value="3">jsYesNoCancel</option>
    		<option value="4">jsYesNo</option>
    		<option value="5">jsRetryCancel</option>
    	</select>
    <hr>
    <label>Group 2: </label>
    	<select name="G2">
    		<option value="0" selected>(none)</option>
    		<option value="16">jsCritical</option>
    		<option value="32">jsQuestion</option>
    		<option value="48">jsExclamation</option>
    		<option value="64">jsInformation</option>
    	</select>
    <hr>
    <label>Group 3: </label>
    	<select name="G3">
    		<option value="0" selected>jsDefaultButton1</option>
    		<option value="256">jsDefaultButton2</option>
    		<option value="512">jsDefaultButton3</option>
    		<option value="768">jsDefaultButton4</option>
    	</select>
    <hr>
    <label>Group 4: </label>
    	<select name="G4">
    		<option value="0" selected>jsApplicationModal</option>
    		<option value="4096">jsSystemModal</option>
    	</select>
    </fieldset>
    <input type="button" value="Unpack" 
    onclick="unpack(
    	+(G1.options[G1.selectedIndex].value) | +(G2.options[G2.selectedIndex].value) | 
    	+(G3.options[G3.selectedIndex].value) | +(G4.options[G4.selectedIndex].value)
    )">
    </form>
    </body>
    Last edited by codegoboom; 11-30-2004 at 06:36 PM. Reason: bit
    *this message will self destruct in n-seconds*

  • #5
    Regular Coder
    Join Date
    Dec 2003
    Posts
    367
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Most languages have bit shifting operators and bitwise logical operators that can do that. A bitwise logical operator is like the normal logical operators (AND, OR, NOT, etc.), but it works on every bit separately. In C/C++/Java (I think Javascript too) the logical operators are & for AND (as opposed to && for the normal AND), | for OR, ~ for NOT, ^ for XOR. Bitshift operators are << and >>.
    Some samples:
    Code:
    a =     10001011
    ~a =    01110100
    b =     00111101
    a | b = 10111111
    a & b = 00001001
    Using these operators you can easily extract the "fields" in a bitfield. For instance, if you want to extract bits 3 and 4 from n:
    Code:
    // bits 3 and 4 -> 00001100 binary -> 12 decimal, so
    flag = n & 12;
    shmoove
    Last edited by shmoove; 11-30-2004 at 05:19 PM.

  • #6
    Regular Coder
    Join Date
    Aug 2004
    Location
    codegoboom@yahoo.com
    Posts
    999
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Alrighty then... you know, I think my simple mind has twiddled one too many bits for the time being, so I'll look back on this later, maybe.
    *this message will self destruct in n-seconds*

  • #7
    Regular Coder
    Join Date
    Aug 2004
    Location
    codegoboom@yahoo.com
    Posts
    999
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Ok, I got it, hopefully...

    The nibbles have to be tested in descending order--to handle dependent bits (like 1,3,5)...

    and if a field exists, then "n AND field" will equal "field".

    So:
    Code:
    function unpack(n)
    {
    	switch(true)
    	{
    		case (n & 5) == 5:
    			alert("jsRetryCancel");
    			break;
    		case (n & 4) == 4:
    			alert("jsYesNo");
    			break;
    		case (n & 3) == 3:
    			alert("jsYesNoCancel");
    			break;
    		case (n & 2) == 2:
    			alert("jsAbortRetryIgnore");
    			break;
    		case (n & 1) == 1:
    			alert("jsOKCancel");
    			break;
    		default:
    			alert("jsOKOnly");
    	}
    	switch(true)
    	{
    		case (n & 64) == 64:
    			alert("jsInformation");
    			break;
    		case (n & 48) == 48:
    			alert("jsExclamation");
    			break;
    		case (n & 32) == 32:
    			alert("jsQuestion");
    			break;
    		case (n & 16) == 16:
    			alert("jsCritical");
    			break;
    	}
    	switch(true)
    	{
    		case (n & 768) == 768:
    			alert("jsDefaultButton4");
    			break;
    		case (n & 512) == 512:
    			alert("jsDefaultButton3");
    			break;
    		case (n & 256) == 256:
    			alert("jsDefaultButton2");
    			break;
    		default:
    			alert("jsDefaultButton1");
    	}
    	switch(true)
    	{
    		case (n & 4096) == 4096:
    			alert("jsSystemModal");
    			break;
    		default:
    			alert("jsApplicationModal");
    	}
    }
    Am I wrong?
    *this message will self destruct in n-seconds*

  • #8
    Regular Coder
    Join Date
    Dec 2003
    Posts
    367
    Thanks
    0
    Thanked 0 Times in 0 Posts
    That is one way to go about it.
    Another way would be to extract the exclusive flags. I'm not exactly familiar with these constants so I'll be going from the code you posted. It looks like the first set of exclusive options are 0-5, so they need the 3 lowest order bits. You can extract them using 7 (or 111 in binary):
    Code:
    buttonsFlag = n & 7;
    For the second set, the options range between 16 and 64. So you want a number where all those bits are on. That would be 112 (or 1110000, or 16+32+64), so the second flag can be extracted like so:
    Code:
    typeFlag = n & 112;
    The third set uses bits 9 and 10 (aka 256 and 512) so it can be extracted using 768 (1100000000):
    Code:
    defaultFlag = n & 768;
    The last set uses one bit, the one for 4096, so we extract it with 4096:
    Code:
    modalFlag = n & 4096;
    Then you can use simpler switch statements on these new flags, to get:
    Code:
    unpack(n) {
      buttonsFlag = n & 7;
      typeFlag = n & 112;
      defaultFlag = n & 768;
      modalFlag = n & 4096;
    
      switch (buttonsFlag) {
        case 0:
          alert("jsOKOnly");
          break;
        case 1:
          alert("jsOKCancel");
          break;
        case 2:
          alert("jsAbortRetryIgnore");
          break;
        case 3:
          alert("jsYesNoCancel");
          break;
        case 4:
          alert("jsYesNo");
          break;
        case 5:
          alert("jsRetryCancel");
          break;
      }
      switch (typeFlag) {
        case 16:
          alert("jsCritical");
          break;
        case 32:
          alert("jsQuestion");
          break;
        case 48:
          alert("jsExclamation");
          break;
        case 64:
          alert("jsInformation");
          break;
      }
      // well, you get my drift.
    }
    If you really want to come to grips with this I suggest you grab a pencil and a piece of paper, and actually write down all the binary values, and play around with the various operations on them.

    shmoove

  • #9
    Regular Coder
    Join Date
    Aug 2004
    Location
    codegoboom@yahoo.com
    Posts
    999
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Aha... that makes more sense. Thanks!
    *this message will self destruct in n-seconds*


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •