Bit Masking & Unmasking

Before jumping into this post, try to read this post to know how to set & clear a bit. 

There are three reading modes: 1) Physical book 2) Ebook 3) Audiobook

Books are identified by a unique number, and this would vary based on the modes. For example, physical books have both ISBN & UUID. ISBN will be a 32-bit value. Similarly, UUID will be a 32-bit value. These both together combine a 64bit unique identifier for Physical copies. 

Alternatively, Ebook has the only UUID which is 32 bit. Again, Audiobook has only audiobook id which is again 32 bit. The requirement is to store the book id as a 64-bit variable based on modes which will also further used to identify the reading mode back. 

Note: 32-bit UUID always has the MSB set. 

Write a program to print the  64-bit book id based on the user given mode. From the 64-bit  book id derive & display the identifier as 32 bit value. Use bitwise operations and verify the maximum 32-bit value.

Click here to debug.

#include <stdio.h>

#define MODE_PHYSICAL_BOOK 1  /* (1(16bit) + UUID(32bit)) & ISBN(32bit)*/
#define MODE_EBOOK         2  /* 0(32bit) & (1(16bit) + UUID(32bit)) */
#define MODE_AUDIOBOOK     3  /* 0(32bit) & AUDIO BOOK ID(32bit) */

#define ROSE_UUID_ID_MASK(X)                 (X | 1 << 31)
#define ROSE_PHYSICAL_BOOK_UUID_ID_UNMASK(X) (((X & 0XFFFFFFFF00000000) >> 32) & ~(1 << 31))
#define ROSE_EBOOK_UUID_ID_UNMASK(X)         ((X & 0X00000000FFFFFFFF) & ~(1 << 31))
#define ROSE_ISBN_ID_UNMASK(X)               (X & 0X00000000FFFFFFFF)

/*
 * BOOK ID for ROSE is 64-bit.So masking 32 bit to 64 bit and the BOOK-ID as follows
 * PHYSICAL BOOK (32bits(uuid-id) + 32bits (isbn id))
 * EBOOK         (32bits (0) + 32bits (uuid-id))
 * AUDIOBOOK     (32bits (0) + 32bits (AUDIO-BOOK id))
 */
#define ROSE_MASK_TO_BOOK_ID(X,Y)  (((long long int)X) << 32 | ((long long int)Y))


int main()
{
    int mode = 0;
    unsigned int uuid_id = 0; /* Max UUID id 65535 */
    unsigned int isbn_id = 0; /* Max isbn id 4294967294 */
    unsigned int u_isbn_id = 0;
    long long int book_id = 0;
    unsigned int m_uuid_id = 0; /* Max UUID id 2147549183 */
    unsigned int u_uuid_id = 0; /* Max UUID id 65535 */

    printf("Enter the reading mode(1/2/3): ");
    scanf("%d", &mode);
    switch(mode) {
        case MODE_PHYSICAL_BOOK:
            printf("\nEnter PHYSICAL_BOOK uuid id: ");
            scanf("%d", &uuid_id);
            printf("\nEnter PHYSICAL_BOOK ISBN id: ");
            scanf("%d", &isbn_id);
            m_uuid_id = ROSE_UUID_ID_MASK(uuid_id);
            book_id = ROSE_MASK_TO_BOOK_ID(m_uuid_id, isbn_id);
            printf("\n Masked UUID id %u BOOK id %llu\n", m_uuid_id, book_id);
            u_uuid_id = ROSE_PHYSICAL_BOOK_UUID_ID_UNMASK(book_id);
            u_isbn_id = ROSE_ISBN_ID_UNMASK(book_id);
            printf("\n Unmasked UUID id %u isbn id %u\n", u_uuid_id, u_isbn_id);
            break;
        case MODE_EBOOK:
            printf("\nEnter EBOOK uuid id: ");
            scanf("%d", &uuid_id);
            m_uuid_id = ROSE_UUID_ID_MASK(uuid_id);
            book_id = ROSE_MASK_TO_BOOK_ID(0, m_uuid_id);
            printf("\n Masked UUID id %u BOOK id %llu\n", m_uuid_id, book_id);
            u_uuid_id = ROSE_EBOOK_UUID_ID_UNMASK(book_id);
            printf("\n Unmasked UUID id %u isbn id %u\n", u_uuid_id, u_isbn_id);
            break;
        case MODE_AUDIOBOOK:
            printf("\nEnter the AUDIO-BOOK id: ");
            scanf("%d", &isbn_id);
            book_id = ROSE_MASK_TO_BOOK_ID(0, isbn_id);
            printf("\n Masked BOOK id %llu\n", book_id);
            u_isbn_id = ROSE_ISBN_ID_UNMASK(book_id);
            printf("\n Unmasked UUID id %u isbn id %u\n", u_uuid_id, u_isbn_id);
            break;
        default:
            printf("\nNot supported reading mode\n");
            break;
    }
    return 0;
}


ROSE_UUID_ID_MASK(X) - This sets the 32nd bit
ROSE_PHYSICAL_BOOK_UUID_ID_UNMASK(X) - Converts the 64bit to 32 and clears the 32nd bit


From this post, you can also get to know how the 64-bit is converted into 32-bit value using ((X & 0XFFFFFFFF00000000) >> 32) in the below preprocessor macro. 

#define ROSE_PHYSICAL_BOOK_UUID_ID_UNMASK(X) (((X & 0XFFFFFFFF00000000) >> 32) & ~(1 << 31))


Reference:

Own knowledge ;-)


Comments