Edoardo Remondini
Edoardo Remondini

Reputation: 13

Need help in decoding Bitmask flags in Javascript

beginner in using bitwise operators here. I understand the differences between them, however I'm not able to decode correctly the user language from them. basically the backend gives me a number which I need to use for decoding user language.

static const int TlvLanguageMask = 0x0700;
static const int TlvEnglish = 0x0000;
static const int TlvFrench = 0x0100;
static const int TlvSwedish = 0x0200;
static const int TlvCzech = 0x0300;
static const int TlvGerman = 0x0400;
static const int TlvSpanish = 0x0500;
static const int TlvItalian = 0x0600;
static const int TlvRomanian = 0x0700;

this is what the backend written in C++ uses for setting the languages. in my frontend written in Javascript I did the following thing:

 function decodeLanguagevalue(Languagecode){
  let language;
  const languages={
  languagemask:1792,//1110 0000 000
  english:0,//0
  french:128<<1,//256 -->1000 0000 0
  swedish:128<<2,//512-->1000 0000 00
  czech:512^256,//768 -->1100 0000 00 french+swedish?
  German:128<<3,//1024-->1000 0000 000
  Spanish:1024^256,//1280-->1010 0000 000 german+french?
  Italian:1280^256,//1536--> 1100 0000 000 spanish+french?
  Romanian:1536^256//1792--> 1110 0000 000 italian+french?


}
  switch (Languagecode) {
    case Languagecode & languages.english:
      language="UK"
      break;
    case Languagecode & languages.french:
      language="French"
      break;
    case Languagecode & languages.swedish:
      language="Swedish"
      break;
    case Languagecode  & languages.french & languages.swedish:
      language="CZech"
      break;
    case Languagecode & languages.German:
      language="German"
      break;
    case Languagecode & languages.German & languages.french:
      language="Spanish"
      break;
    case Languagecode & languages.Spanish & languages.french:
      language="Italian"
      break;
    case Languagecode & languages.Italian & languages.french:
      language="Romanian" 
      break;
    default:
      language="Unknown"
      break;
  }
  return language

}

however this function always returns me Unknown. This basically means that I messed up with bitwise operators on the frontend.Can someone enlight me on these and help me decoding them correctly? thank you

EDIT 23/05

function decodeLanguagevalue(Languagecode){
  let language;
  const languages={
    languagemask:0x0700,//1110 0000 000 //0x0700
    english:0x0000,//0 //0x0000
    french:0x0100,//256 -->1000 0000 //0x0100
    swedish:0x0200,//512-->1000 0000 00 //0x0200
    czech:0x0300,//768 -->1100 0000 00  //0x0300
    German:0x0400,//1024-->1000 0000 000 //0x0400
    Spanish:0x0500,//1280-->1010 0000 000  //0x0500
    Italian:0x0600,//1536--> 1100 0000 000 //0x0600
    Romanian:0x0700//1792--> 1110 0000 000  //0x0700
  }
  
  if((Languagecode & languages.english)==languages.english){
    language='English'
  }
  if((Languagecode & languages.french)==languages.french){
    language='French'
  }
  if((Languagecode & languages.swedish)==languages.swedish){
    language='Swedish'
  }
  if((Languagecode & languages.czech)==languages.czech){
    language='Czech'
  }
  if((Languagecode & languages.German)==languages.German){
    language='German'
  }
  if((Languagecode & languages.Spanish)==languages.Spanish){
    language='Spanish'
  }
  if((Languagecode & languages.Italian)==languages.Italian){
    language='Italian'
  }
  if((Languagecode & languages.Romanian)==languages.Romanian){
    language='Romanian'
  }

  language===undefined ? language='unknown' : language
  
  return language
  

}

Upvotes: 1

Views: 294

Answers (2)

trincot
trincot

Reputation: 349873

The problem with your switch...case statement is that it checks that Languagecode is equal to Languagecode & languages.english, which can only be true when languages.english has at least all 1-bits that Languagecode has, but if Languagecode also includes non-language related bits (outside of the language mask range), this can never be true. The same then happens with the other case parts of the switch statement...

I would do this:

const languages = ["English", "French", "Swedish", "Czech", "German", "Spanish", "Italian", "Romanian"];

function decodeLanguagevalue( code ) {
  const languageId = (code >> 8) & 7; // get the three bits of interest in the lowest bits
  return languages[languageId];
}

Explanation

Initially, the language id is encoded in the three bits marked as * in the below integer (in binary representation -- this corresponds to your languagemask):

???? ?*** ???? ????

The question marks indicate bits that do not interest us when it comes to finding out the language. So we start by "removing" the bits at the right side of those that interest us. We can shift them out, using the right-shift operator (>>). If we shift once, we get this:

0??? ??** *??? ????
───────────────────>>

Note how at the left side a zero is shifted in, and at the right side a ? is dropped off.

If we continue to shift (up to 8 times), we get this:

0000 0000 ???? ?***
───────────────────>>

As we are not interested in the ? part on the left side either, we kick those out as well, by applying a bit-wise AND operation with 0111:

0000 0000 ???? ?***
0000 0000 0000 0111
─────────────────── AND
0000 0000 0000 0***

So now we have extracted the three bits of interest, and they sit in the least significant bits. That is great, because now the value of the number lies between 0 and 7 (inclusive). This can be used as an index in an array of strings.

Upvotes: 2

Trentium
Trentium

Reputation: 3719

The code as presented encodes the Languagecode as a combination of a bit mask, and a numeric value in the range from 0 to 7. (Note that in binary, the range is 000b to 111b.) Thus, the bit mask is used to reduce the Languagecode to only the 3 binary digits of interest. Then, you simply check the result against the Languagecode value.

Thus, on the client side, the code will appear as...

 const TlvLanguageMask = 0x0700;
 const TlvEnglish = 0x0000;
 const TlvFrench = 0x0100;
    o
    o
    o
 const TlvRomanian = 0x0700;

function decodeLanguagevalue( Languagecode ) {

  let language = 'Unknown';
  switch ( Languagecode & TlvLanguageMask ) {
    case TlvEnglish:
      language = 'English';
      break;
    case TlvFrench:
      language = 'French';
      break;
        o
        o
        o
    case TlvRomanian:
      language = 'Romanian'; 
      break;
  }
  return language;

}

Upvotes: 2

Related Questions