Expiring Today—Celebrate National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x

Visual C++.NET

Microsoft Visual C++ (often abbreviated as MSVC or VC++) is an integrated development environment (IDE) product from Microsoft for the C, C++, and C++/CLI programming languages. It features tools for developing and debugging C++ code, especially code written for the Microsoft Windows API, the DirectX API, and the Microsoft .NET Framework. Many applications require redistributable Visual C++ packages to function correctly and are often installed independently of applications, allowing multiple applications to make use of the package while only having to install it once

Share tech news, updates, or what's on your mind.

Sign up to Post

In Easy String Encryption Using CryptoAPI in C++ I described how to encrypt text and recommended that the encrypted text be stored as a series of hexadecimal digits -- because cyphertext may contain embedded NULLs or other characters that can cause processing problems.

Since then I've worked on an application in which large blocks of binary data must be encoded into hexadecimal rapidly, and when needed, decoded back to binary just as rapidly.  In the earlier article, I provided a sort of "throw-away" hex encoder/decoder, but I felt that I needed something that was more efficient for production work.

In this article, I'll explore some hex encode/decode options, including the one supported by the CryptoAPI, and at the end of the article, I'll present the ultra-fast functions that ended up in my production code.

Observe the ordering of characters in an ASCII Table The only real issue with hex encoding is that there is a gap between the 9 and the A.  Most of the complications come when dealing with that.

How to Encode to Hexadecimal
Your binary source byte is 8 bits.  Take the data 4 bits at a time (values 0-15).  If that value is 0-9, then just add '0' (0x30).  If the value is 10-15, then add 0x37 instead.  That gives you a hex digit ('0', '1',...,'9','A',..., 'F').  Output the resulting high hex digit followed by the low hex digit.

Open in new window

3
 
LVL 49

Author Comment

by:DanRollins
Comment Utility
Here's the EE Terms of Use page: http://www.experts-exchange.com/termsOfUse.jsp

I know of no prohibition or limitation on use of any source code provided in an EE article or Q/A response.  Frankly, the whole point of this site is to provide usable solutions, so it would be strange if there were prohibitions on usage.   As a practical matter, the above code can be used in any way you want.  I'd expect that if you use the code in an article or publication, that you would properly attribute the author and the site.

-- Dan
0
 
LVL 22

Expert Comment

by:ambience
Comment Utility
Don't you think a Duff's device applied would make it somewhat faster? This part

     for (int j=0; j<nSrcLen; j++ ) {
            *pwDest= pwHex[*pSrc];
            pwDest++; pSrc++;
      }

can be unrolled and rumors are that duff's device achieves for example 30% faster with gcc. I believe its definitely worth a try.

#define SafeMacro(statment) \
	do { statment; } while (0)

#define DuffLoop(aCount, statment) \
	SafeMacro( \
		auto count_ = (aCount); \
		auto times_ = (count_ + 7) >> 3; \
		switch (count_ & 7){ \
		case 0: do { statment; \
		case 7: statment; \
		case 6: statment; \
		case 5: statment; \
		case 4: statment; \
		case 3: statment; \
		case 2: statment; \
		case 1: statment; \
		} while (--times_ > 0); \
		} \
	)

#define DuffLoopChecked(aCount, statment) \
	SafeMacro( if(aCount) { DuffLoop((aCount), statment); } )

// 
DuffLoopChecked(
	nSrcLen, 
	*pwDest++= pwHex[*pSrc++];
);

Open in new window

0
Important Lessons on Recovering from Petya
LVL 10
Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

The following diagram presents a diamond class hierarchy:
DiamondAs depicted, diamond inheritance denotes when two classes (e.g., CDerived1 and CDerived2), separately extending a common base class (e.g., CBase), are sub classed simultaneously by a fourth class (e.g., CTest).

The following is how one would expect the diagram to be implemented:
#include <stdio.h>

class CBase
{
public:
	virtual void test()
	{
		printf("CBase::test()\r\n");
	}
};

class CDerived1 : public CBase
{
};

class CDerived2 : public CBase
{
};

class CTest : public CDerived1, public CDerived2
{
};

int main()
{
	CTest test;
	test.test();
	return 0;
}

Open in new window

However, the Microsoft VC+ 2005 .NET compiler gives the following message:
1>------ Build started: Project: vft_test, Configuration: Debug Win32 ------
1>Compiling...
1>main_romb.cpp
1>c:\source\vft_test\vft_test\main_romb.cpp(27) : error C2385: ambiguous access of 'test'
1>        could be the 'test' in base 'CBase'
1>        or could be the 'test' in base 'CBase'
1>c:\source\vft_test\vft_test\main_romb.cpp(27) : error C3861: 'test': identifier not found
1>Build log was saved at "file://c:\Source\vft_test\vft_test\Debug\BuildLog.htm"
1>vft_test - 2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Open in new window


Since CDerived1 and CDerived2 can have very different implementations of CBase::test(), the compiler is unsure which CTest derives.  This is the so called "Diamond problem" or even "Dreaded Diamond".

How to deal with this "dread"?

The following code will give you a clue:
#include <stdio.h>

class CBase
{

public:
	CBase()
	{
		printf("CBase::CBase()");
	}

	virtual void test()
	{
		printf("CBase::test()\r\n");
	}
};

class CDerived1 : public CBase
{

public:
	CDerived1()
	{
		printf("CDerived1::CDerived1()");
	}
};

class CDerived2 : public CBase
{

public:
	CDerived2()
	{
		printf("CDerived1::CDerived1()");
	}
};

class CTest : public CDerived1, public CDerived2
{

public:
	CTest()
	{
		printf("CTest::CTest()");
	}
};

int main()
{
	CTest test;
	return 0;
}

Open in new window


This program is compiled successfully and works:
Object creation process
Of course, you know how CTest object is created.  It derives, firstly, from CDerived1 object, that inherits from CBase, and, secondly, CTest derives from CDerived2 that also inherits from CBase.  So the compiler (probably any compiler) creates CBase object, then CDerived1, and now it needs to create CBase again, ..., etc., we got 2 CBase objects!

The diagram did not show that the CBase class appears twice in the class hierarchy.

C++ provides a technique for such case.  The declaration of the CBase class as virtual solves the situation:

Open in new window

4
 
LVL 60

Expert Comment

by:Kevin Cross
Comment Utility
Good job, pgnatyuk!
You have my vote above.
0
 

Expert Comment

by:data4use
Comment Utility
Thanks a lot man, it helped me
0

Visual C++.NET

Microsoft Visual C++ (often abbreviated as MSVC or VC++) is an integrated development environment (IDE) product from Microsoft for the C, C++, and C++/CLI programming languages. It features tools for developing and debugging C++ code, especially code written for the Microsoft Windows API, the DirectX API, and the Microsoft .NET Framework. Many applications require redistributable Visual C++ packages to function correctly and are often installed independently of applications, allowing multiple applications to make use of the package while only having to install it once

Top Experts In
Visual C++.NET
<
Monthly
>