Click here to Skip to main content
15,890,579 members
Articles / Desktop Programming / MFC
Article

CABMBitSet and CFlexBitSet - Compact Storage with easy interface

Rate me:
Please Sign up or sign in to vote.
3.00/5 (2 votes)
29 Mar 2005CPOL5 min read 33.4K   491   16   7
Creating compact storage for a set of BOOLs, enums, or other sets of limited value data.

Sample Image

Introduction

Dealing in both the embedded and GUI world, there are many times where I find that I want to store large numbers of BOOL flags or enums that have a limited range, say 0 to 7 for example, but I do not want to take up an INT to store such a thing to disk. Historically, I have followed the steps of those before me at work and created integers and masks to grab the correct bit to store or retrieve the value. Recently, a coworker came up with a nice idea of abstracting this to be viewed as an array. I decided that I wanted to try that idea from scratch and created CABMBitSet template class.

The idea was to be able to access a bit with the array ‘[]’ operator for setting and retrieving the value such that it would accept a BOOL for setting the value and present a BOOL when retrieving the value. Then I wanted to go a step further.

Why limit the interface to BOOL? Very often, I store enum values where the range of the enum is rather small and certainly not 32,000(ish). So I created CFlexBitSet template class. This one allows you to not only define how many elements are in the array, but also how many bits each element needs and how it should appear (class type (BOOL, int, etc.)) to the outside code.

Both allow you to:

  • Set/Get the value with the ‘[]’ operator.
  • Get the bit values in string format (intended for debugging mostly).
  • Get/Set the array of bits from your own array of UINT32 values that would be saved to disk.

Background

Most will find this code overkill... That’s ok. I wrote it for fun and to make my life easier. If you find it useful, that’s just a bonus.

Also, you will see commenting in the code in the style of CCDoc. If you don’t have the tool (just an EXE) and would like to reproduce the documentation, a quick search for CCDoc will find it at SF. The documentation is included in the demo project download if you want to check out the HTML documentation...

Using the code

Using it is fairly straightforward. Below I show the general type of interaction and leave the saving to file up to the user. I noted another article that had the user code pass in a (FILE*) for saving / retrieving the value. I decided against this as there are too many things one may want to do with the data before sending to the file, besides the user code may not want to use a (FILE*) for persisting to disk. Therefore, that part is left to the user code.

  1. typedef the template to your needs - For this step, you need to know how many elements you are working with.
    typedef CFlexBitSet<10,1,BOOL> CFlexBitSet_10_BOOL;
    typedef CFlexBitSet<17,2,int> CFlexBitSet_17_int2;
    typedef CABMBitSet<17> CBitSetBOOL17;
  2. Declare an instance of the variable for use.
    CFlexBitSet_10_BOOL m_BitSet;
    CFlexBitSet_17_int2 m_BitSet2int;
    CBitSetBOOL17 m_BoolSet;
  3. Set or get values from the variable.
      m_BitSet2int[ m_iElement ] = m_iSetValue;
      m_BitSet[2] = TRUE;
      m_BoolSet[3] = TRUE;
    
    if ( m_BoolSet[2] ) {
      ...
    }
    if ( m_BitSet[2] ) {
      ...
    }
    If(m_BitSet2int[ m_iElement ] == iSomeTestValue){
      ...
    }
  4. Get or Set the value (as a whole) from outside storage (for persisting data between instances).
    UINT32* pTest = NULL;
    int SizeArray;
    
    BitSet.GetRawData(pTest, SizeArray);
    
    StoreUINT32ArrayToFile( pTest, SizeArray );
    //some custom code you (user code) write
    
         <  ... time passes and we need to get it from the file ... >
    
    GetFileStoredUINTArrayFromFile( pTest, SizeArray );
    //some custom code you (user code) write
    
    BitSet.SetRawData(pTest, SizeArray);
    delete[] pTest;

Points of Interest

  • Q: Hey, why did you make this a template class? This could have been done in a more flexible manner if you made the template parameters part of the constructor.

    A: Hmmmm... you have a point there. However, I wrote it as a template anyway. Maybe I should change it, but for now, this seems to suit all my needs.

  • Q: What’s with the CCDoc comments?

    A: Ever since I started trying CCDoc, I fell in love with it. I often write code that I want to use later but when I want to use it, I want a document that I can refer to without having to trod through the code. CCDoc provides that type of documentation that I find useful... as long as I comment it sufficiently.

  • Q: Why two classes? The CFlexBitSet can do the duty of both.

    A: True. But I wrote the CABMBitSet for the immediate need of a large set of BOOL flags that I needed to store. But after I wrote that one, I wanted to see how much it would take to convert it to handle elements that might need 2, 3, or more bits (up to 31) in the same manner.

  • Q: In your example, you use hard coded index numbers to access certain elements. Is that wise?

    A: Of course not. In practice, I would substitute either values that were ‘#define’ or an enum. But hey, in an example, I wanted to keep it simple.

  • Q: Why should I use your code?

    A: You shouldn’t. ...unless it suits your needs and you do not want to write it all over again. Knowing is half the battle, ...do unto others..., etc.

  • Q: I like the way you used an internal class to allow the use of ‘[]’ operator for set and get.

    A: Thanks, but I can’t take the credit for that idea. I got that from a friend of mine, JAS, and he has also found that idea out there on the web somewhere. I just wanted to make sure the idea was formally placed out there... or rather, here. Can I call this code mine? Not really. I do not even claim complete ownership of the idea. But hey, I can’t stop you either, nor would I try. Hehehe, but then again, why would you?

  • Q: Hey, want to go grab a beer?

    A: Sure, let’s go!

  • Q: Why does the dialog use Courier New for the font?

    A: Because the string representation GetStrRepresentation(TRUE,FALSE); uses two lines and without a fixed pitch font, and that can look goofy. If you want to get around this in your testing, then send it to a MessageBox( ... ) and then when the box appears, hit <ctrl>+c<ctrl>, open Notepad, and paste it there. Notepad, I believe by default, uses a fixed pitch font.

History

(2005-03-27) My initial release.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
...I'm really starting to get into C++/CLI... very nice!

Comments and Discussions

 
GeneralMy vote of 1 Pin
Brian Shifrin10-Feb-10 8:49
Brian Shifrin10-Feb-10 8:49 
Generalbitfields Pin
umeca745-Apr-05 3:49
umeca745-Apr-05 3:49 
you may not be aware that C++ already has such bitfields (in fact all the way back to C)

struct example {
	unsigned int m_bSaveSettings:1;
	unsigned int m_bConsole:1;
	unsigned int m_bBeepOnErrors:2;
	unsigned int m_bPlainByteFmt:1;
	unsigned int m_bShowHidden:1;
	unsigned int m_bPlainIcons:2;
	unsigned int m_bEat1Klik:1;
};

etc
GeneralRe: bitfields Pin
BuddyLeeJr5-Apr-05 17:19
BuddyLeeJr5-Apr-05 17:19 
GeneralRe: bitfields Pin
BuddyLeeJr5-Apr-05 17:34
BuddyLeeJr5-Apr-05 17:34 
QuestionAny chance coming up with a VC 6 version? Pin
WREY30-Mar-05 1:28
WREY30-Mar-05 1:28 
AnswerRe: Any chance coming up with a VC 6 version? Pin
BuddyLeeJr30-Mar-05 2:17
BuddyLeeJr30-Mar-05 2:17 
AnswerRe: Any chance coming up with a VC 6 version? Pin
BuddyLeeJr30-Mar-05 18:42
BuddyLeeJr30-Mar-05 18:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.