CNumberFormat: A class for bit-field extraction out from 32 bit value values






3.80/5 (7 votes)
Jan 12, 2005
7 min read

44612

1297
An MFC class for fast extraction and interpretation of values from a 32 bit provided value.
Table of Contents
- Purpose
- Environment used
- Adding the CNumberFormat class to your project
- How to use this class
- Code Documentation
- Provided Files
- Some words about the demo application provided
- Disclaimer
- Terms of use
- ChangeLog
Purpose
The motivation in writing this CNumberFormat
class was:
- Fast parsing of data retrieved from some hardware registers and interpret the values stored as separated fields. (E.g., look only on the field located between bit
15
and bit12
as a signed 4 bit width value.) - Capable to interpret the values as signed or unsigned values according to the needs.
- Provide formatted strings in case the values are displayed on some kind of user interface.
The following considerations were taken:
- Numbers are stored as Little-Endian numbers. If you plan to use this class for Big-Endian byte ordering, you should tailor it for your needs. Currently there is no check about the Endianness used. (See Basic concepts on Endianness[^] in this site if you need help with Endianness...)
- Numbers are limited up to 32 bits. If you plan to use this class for 64 bits, some changes are also required.
I used this class to parse hundreds of fields stored in registers retrieved from some hardware to produce some statistics and graphs. The whole register-map was read periodically at a rate of 10 msec.
Environment used
This class was initially developed using VC 6.0 (Visual Studio C++ 6.0), and now I'm using VC 7.1 (Visual Studio C++ .NET 2003). The demo application will compile only on VC 7.1 due that I'm using some MFC stuff not present in VC 6.0. The class CNumberFormat
will compile also in VC 6.0..
Adding the CNumberFormat class to your project
Make sure you have got two files: NumberFormat.h and NumberFormat.cpp, copy them to your project directory.
Open your project in your developing environment and add these files to your project.
To the relevant files, add the following line in your includes section:
...
#include "NumberFormat.h"
...
Now you are ready to use this class.
How to use this class
Construction
The CNumberFormat
has a default constructor, but you also can build one by providing some attributes such as startBit
, endBit
and initial value. If these values are not provided, the new CNumberFormat
item will have a startBit=0
, endBit=31
and value=0
.
... CNumberFormat format; // Build a CNumberFormat, with startBit=0, endBit=31, value=0. CNumberFormar *pFormat = new CNumberFormat(15,18); // startBit=15, endBit=18, value=0. ...
Copy-Construction is also possible from a reference or pointer (see below).
Duplication
Duplicating a CNumberFormat
also is possible in different ways:
... // // Building a new format from an existing one // CNumberFormat newFormat(format); // Copy format to the new newFormat. CNumberFormar anotherFormat(pFormat); // Copy pFormat to the new anotherFormat. newFormat = anotherFormat; // copy via assignment operator.. newFormat.Copy(pSourceNumberFormat); // Copy from a pointer to a CNumberFormat. newFormat.Copy(sourceNumberFormat); // Copy from a CNumberFormat item. (reference) ...
Just take care not to use a NULL
pointer, otherwise you will get a default CNumberFormat
item.
Attributes
Any time, the different attributes can be set using any of the provided setter functions.
The following table lists the different attributes stored on a CNumberFormat
. For clarity, the names here are not the same as the private members used on the class.
radix |
The format of the field, used to format strings. (ERadix enum type) |
|
The range is built from the The The The Using these values, an internal mask is built for getting the relevant field from the stored/provided number. |
noBits |
Number of bits the field contains. ((endBit-startBit)+1 ) |
value |
The 32 bit unsigned value provided. From this value, the field is extracted. |
There is no setter for the noBits
attribute. This attribute is set using the SetBitRange()
, or SetStartBit()
, or SetEndBit()
, or during construction.
There is no getter for the value
attribute. (I did not need such one!)
Field Extraction
Let's assume we read a register containing a 'phase-value' field that is stored on bits 11
down to 8
. (A 4 bit field.)
The CNumberFormat
that describes the phase-value can be defined and used as follows:
... CNumberFormat phaseValueFormat; unsigned long ul; signed long sl; unsigned long value; phaseValueFormat.SetBitRange(8,11); ... // // Read the 32bit unsigned register and store // in the phaseValueFormat item // value = *HW_REGISTER; phaseValueFormat.SetValue(value); ... // Get the values stored on this field (signed and unsigned) ul = phaseValueFormat.GetUnsigned(); sl = phaseValueFormat.GetSigned(); .. // Another way to do it. ul = phaseValueFormat.GetUnsigned(value); // Just extract the field from value. sl = phaseValueFormat.GetSigned(*HW_REGISTER); // Translate on-the-fly. ...
From the experience I have with this class, most of the time you will be doing 'on-the-fly' translations, as shown in the last line on the code above.
Formatting
If you need to provide a string containing the field value, you need also to set the radix
of the value you want to display. The following enum
is defined on this class for this purpose. (You may use the enumerated constants or just an integer for setting the radix for the format of the field to be extracted. From the NumberFormat.h header file:)
enum ERadix { UNSIGNED_RADIX = 0, ///< Display value as unsigned decimal. SIGNED_RADIX, ///< Display value as signed decimal. HEXADECIMAL_RADIX, ///< Display value as unsigned hexadecimal (0x...) NO_RADIX ///< Don't display value. };
For generating a CString
containing the formatted number, do as follows:
... // Produce an hexadecimal string when required. phaseValueFormat.SetRadix(CNumberFormat::HEXADECIMAL_RADIX); CString phaseValueText1 = phaseValueFormat.GetString(); // Get the value stored.. CString phaseValueText2 = phaseValueFormat.GetString(*HW_REGISTER); // Translate on-the-fly... ...
If you need a string describing the field range, you can use the GetRangeString()
method.
That is all Folks!
Code Documentation
The code contains DOxygen comments, used to generate HTML documentation out of the code. I strongly advice you to use such a tool, directly or indirectly.
DOxygen is a documentation system for C++, C, Java, Objective-C, IDL (CORBA and Microsoft flavors) and to some extent PHP, C# and D. It can be found in www.doxygen.org[^].
The companion help file was generated using the KingsTools[^] Visual Studio .NET Add-In by SteveKing[^], This add-in contains several useful tools you may like to have integrated in your developing environment. (DOxygen, code-statistics, syntax coloring, etc.).
Thanks to SteveKing for this tool, and his disclaimer note I'm using in my code.
Provided Files
Source files:
- NumberFormat.h and
- NumberFormat.cpp
Some words about the demo application provided
Although the demo application is overkill for showing the usage of this class, I hope that this demo may help others also on how to use timers, virtual-list controls, etc. If you want to focus only on the CNumberFormat
class, take a look on the addition of new ranges using the CArray
template and in the method CDemoDlg::OnListLvnGetdispinfo()
on the provided demo source-code.
The demo application will shuffle a 32 bit value out of the ::GetTickCount()
system call every ~2sec to give the user the time to look on the results. The shuffled value is displayed on a read-only edit box (hexadecimal and binary formats).
The table shows the same value parsed according to the bit-range and radix selected. The columns of the table are:
Bits: | Number of bits on the extracted value (from 1 up to 32). |
Range: | The endBit and startBit that describes the extracted value. The formatted string is as follows: "[endBit:startBit] ". |
Unsigned: | The unsigned decimal representation of the extracted field. |
Signed: | The signed or twos-complement representation of the extracted field. |
Hexa: | The unsigned hexadecimal representation of the extracted field. |
Two buttons are also provided, one for adding a new range to the end of the list (you may add any number or new range descriptions), and a delete-all button for removing the contents of the list.
All the numbers on the table are extracted from the same victim value as displayed on the read-only edit box.
Disclaimer
This code and the accompanying files are provided "as is" with no expressed or implied warranty. No responsibilities for possible damages, or side effects in its functionality. The user must assume the entire risk of using this code. The author accepts no liability if it causes any damage to your computer, causes your pet to fall ill, increases baldness or makes your car start emitting strange noises when you start it up. This code has no bugs, just undocumented features!.
Terms of use
This code is free for personal use, or freeware applications. If you plan to use this code in a commercial or shareware application, you are politely asked to contact the author for his permission.
ChangeLog
Date | Rev. | Description |
2005/Jan/09 | 1.0 | Debut in CodeProject. |
2002/May/11 | --- | Created. |
Epilogue
Hope that this simple class is useful for you.
To help other users in CodeProject, please Rate this Article :)