Set FourCC value in C ++

I want to set FourCC value in C ++, i.e. an unsigned integer of 4 bytes.

I assume the obvious way is #define, for example.

#define FOURCC(a,b,c,d) ( (uint32) (((d)<<24) | ((c)<<16) | ((b)<<8) | (a)) ) 

and then:

 uint32 id( FOURCC('b','l','a','h') ); 

What is the most elegant way you can do this?

+4
source share
11 answers

You can make this a compile time constant using:

 template <int a, int b, int c, int d> struct FourCC { static const unsigned int value = (((((d << 8) | c) << 8) | b) << 8) | a; }; unsigned int id(FourCC<'a', 'b', 'c', 'd'>::value); 

With a little effort, you can check it at compile time so that each number goes between 0 and 255.

+15
source
 uint32_t FourCC = *((uint32_t*)"blah"); 

Why not this?

EDIT: int -> uint32_t.

And no, it does not throw char ** on uint32_t. It drops (char *) to (uint32_t *), then casts (uint32_t *). There is no entity as it assigns uint32_tto uint32_t. The only drawbacks are alignment, and I did not explicitly specify the 32-bit type.

+8
source

or do the same with the built-in function

 inline uint32_t FOURCC(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { return ( (uint32) (((d)<<24) | (uint32_t(c)<<16) | (uint32_t(b)<<8) | uint32_t(a)) ) } 

and avoid macro headaches, but otherwise your approach looks good to me.

+5
source

If I'm not mistaken, can you just use multi-character character constants for this right?

 unsigned int fourCC = 'blah'; 

This is fully compliant with the ANSI / ISO specification, although some compilers will complain a bit. This is how resource types were used in older Macintosh APIs.

+3
source

I do not see anything wrong with your algorithm. But for something like this, I'll just write a function instead of a macro. Macros have many hidden features / issues that can bite you over time.

 uint FourCC(char a, char b, char c, char d) { return ( (uint32) (((d)<<24) | ((c)<<16) | ((b)<<8) | (a)) ); } 
+1
source

Assuming Windows (since FOURCC is a Windows concept), the Win API already provides mmioStringToFOURCC and mmioFOURCC .

+1
source

If a compile-time constant is not required, perhaps the most accurate

 unsigned int FourCCStr(const char (&tag)[5]) { return (((((tag[3] << 8 ) | tag[2]) << 8) | tag[1]) << 8) | tag[0]; } #define FOURCC(tag) FourCCStr(#tag) unsigned int id(FOURCC(blah)); 

Only four-character tags are accepted.

+1
source

Using C ++ 11 constexpr, you can write something like:

 constexpr uint32_t fourcc( char const p[5] ) { return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; } 

And then use it like:

 fourcc( "blah" ); 

pros:

  • More readable
  • if the string argument is known at compile time, then the function is computed at compile time (no overhead at runtime).
  • It does not depend on entity (i.e., the first character of the argument will always be four times the most significant byte).

minuses:

  • Requires a C ++ 11 compiler (or later).
+1
source

Instead of #define, I would probably put almost the same code and rely on the compiler to embed it.

0
source

What about:

 #if BYTE_ORDER == BIG_ENDIAN #define FOURCC(c0,c1,c2,c3) ((uint32) ((((uint32)((uint8)(c0)))<<24) +(((uint32)((uint8)(c1)))<<16)+ (((uint32)((uint8)(c2)))<<8) + ((((uint32)((uint8)(c3)))))) #else #if BYTE_ORDER == LITTLE_ENDIAN #define FOURCC(c3,c2,c1,c0) ((uint32) ((((uint32)((uint8)(c0)))<<24) +(((uint32)((uint8)(c1)))<<16)+ (((uint32)((uint8)(c2)))<<8) + ((((uint32)((uint8)(c3)))))) #else #error BYTE_ORDER not defined #endif #endif 
0
source
 uint32 fcc(char * a) { if( strlen(a) != 4) return 0; //Unknown or unspecified format return ( (uint32) ( ((*(a+3))<<24) | ((*(a+2))<<16) | ((*(a+1))<<8) | (*a) ) ); } 
-1
source

Source: https://habr.com/ru/post/895185/


All Articles