www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - C header file: tagged enumerations

reply Jesse Phillips <Jesse.K.Phillips+D gmail.com> writes:
Windows tends to have these in their header files, what is the 
best way to translate them to D?

https://msdn.microsoft.com/en-us/library/whbyts4t.aspx

Example below. In general a named enum is close enough to the 
same thing, but this example has additional enumerations added 
based on the preprocessor.

Assuming _WIN32_MSI is defined for compile time, what is 
recommended for creating this enum?

typedef enum tagINSTALLMESSAGE
{
// 12 others ...
	INSTALLMESSAGE_INITIALIZE     ,
	INSTALLMESSAGE_TERMINATE      ,
	INSTALLMESSAGE_SHOWDIALOG     ,
#if (_WIN32_MSI >= 500)
	INSTALLMESSAGE_PERFORMANCE    ,
#endif // (_WIN32_MSI >= 500)
#if (_WIN32_MSI >= 400)
	INSTALLMESSAGE_RMFILESINUSE   ,
#endif // (_WIN32_MSI >= 400)
#if (_WIN32_MSI >= 450)
	INSTALLMESSAGE_INSTALLSTART   ,
	INSTALLMESSAGE_INSTALLEND     ,
#endif // (_WIN32_MSI >= 450)
} INSTALLMESSAGE;
Apr 26 2016
next sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Tuesday, 26 April 2016 at 22:57:36 UTC, Jesse Phillips wrote:
 Windows tends to have these in their header files, what is the 
 best way to translate them to D?

 [...]
eunm win32msi = mixin(_WIN32_MSI); static if (win32msi >= 500) .....
Apr 26 2016
next sibling parent Jesse Phillips <Jesse.K.Phillips+D gmail.com> writes:
On Tuesday, 26 April 2016 at 23:33:08 UTC, Stefan Koch wrote:
 On Tuesday, 26 April 2016 at 22:57:36 UTC, Jesse Phillips wrote:
 Windows tends to have these in their header files, what is the 
 best way to translate them to D?

 [...]
eunm win32msi = mixin(_WIN32_MSI); static if (win32msi >= 500) .....
Sorry forgot to mention that static if doesn't allow adding partial declarations, always need to be complete. Or to quote the compiler: "Error: basic type expected, not static"
Apr 26 2016
prev sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 26 April 2016 at 23:33:08 UTC, Stefan Koch wrote:
 static if (win32msi >= 500) .....
Won't work here because static if must have a complete declaration inside it, and the C pattern only has a few elements of the whole inside each #if. D doesn't handle this C pattern well... you basically have to rewrite the whole thing for each version. Personally, I just decide to support all of them and say the older versions with less declarations are less supported...
Apr 26 2016
next sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 4/26/16 7:40 PM, Adam D. Ruppe wrote:
 On Tuesday, 26 April 2016 at 23:33:08 UTC, Stefan Koch wrote:
 static if (win32msi >= 500) .....
Won't work here because static if must have a complete declaration inside it, and the C pattern only has a few elements of the whole inside each #if. D doesn't handle this C pattern well... you basically have to rewrite the whole thing for each version. Personally, I just decide to support all of them and say the older versions with less declarations are less supported...
Hm... doesn't the way the enumeration assigns values mean that on older systems, the values would change for the same symbols? BTW, this enumeration looks terrible. I would flag this as blocking if it were a code review, even in C++. -Steve
Apr 27 2016
parent reply Jesse Phillips <Jesse.K.Phillips+D gmail.com> writes:
On Wednesday, 27 April 2016 at 16:04:13 UTC, Steven Schveighoffer 
wrote:
 BTW, this enumeration looks terrible. I would flag this as 
 blocking if it were a code review, even in C++.

 -Steve
Yeah, I didn't even consider that different versions have different enum values; that is going to be a really good way to break backwards compatibility. Hmm, I wonder if I can make use of UDA and a mixin something like enum tagINSTALLMESSAGE { // 12 others ... INSTALLMESSAGE_INITIALIZE , INSTALLMESSAGE_TERMINATE , INSTALLMESSAGE_SHOWDIALOG , [greaterThan(500)] INSTALLMESSAGE_PERFORMANCE , [greaterThan(400)] INSTALLMESSAGE_RMFILESINUSE , [greaterThan(450)] INSTALLMESSAGE_INSTALLSTART , [greaterThan(450)] INSTALLMESSAGE_INSTALLEND , } mixin taggedEnum!tagINSTALLMESSAGE
Apr 28 2016
parent Jesse Phillips <Jesse.K.Phillips+D gmail.com> writes:
On Thursday, 28 April 2016 at 17:40:23 UTC, Jesse Phillips wrote:
 enum tagINSTALLMESSAGE
 {
 // 12 others ...
 	INSTALLMESSAGE_INITIALIZE     ,
 	INSTALLMESSAGE_TERMINATE      ,
 	INSTALLMESSAGE_SHOWDIALOG     ,
 [greaterThan(500)]
 	INSTALLMESSAGE_PERFORMANCE    ,
 [greaterThan(400)]
 	INSTALLMESSAGE_RMFILESINUSE   ,
 [greaterThan(450)]
 	INSTALLMESSAGE_INSTALLSTART   ,
 [greaterThan(450)]
 	INSTALLMESSAGE_INSTALLEND     ,
 }

 mixin taggedEnum!tagINSTALLMESSAGE
FYI, that is a no since attributes can't be added to enumerations. "Error: basic type expected, not "
Apr 28 2016
prev sibling parent BLM768 <blm768 gmail.com> writes:
On Tuesday, 26 April 2016 at 23:40:24 UTC, Adam D. Ruppe wrote:
 D doesn't handle this C pattern well... you basically have to 
 rewrite the whole thing for each version.
Or you can use the technique that's used in llvm-d: build the enumeration from a string mixin which is generated from a table. It's not necessarily the most elegant solution, but it can eliminate some code duplication.
Apr 27 2016
prev sibling next sibling parent Max Samukha <maxsamukha gmail.com> writes:
On Tuesday, 26 April 2016 at 22:57:36 UTC, Jesse Phillips wrote:
 typedef enum tagINSTALLMESSAGE
 {
 // 12 others ...
 	INSTALLMESSAGE_INITIALIZE     ,
 	INSTALLMESSAGE_TERMINATE      ,
 	INSTALLMESSAGE_SHOWDIALOG     ,
 #if (_WIN32_MSI >= 500)
 	INSTALLMESSAGE_PERFORMANCE    ,
 #endif // (_WIN32_MSI >= 500)
 #if (_WIN32_MSI >= 400)
 	INSTALLMESSAGE_RMFILESINUSE   ,
 #endif // (_WIN32_MSI >= 400)
 #if (_WIN32_MSI >= 450)
 	INSTALLMESSAGE_INSTALLSTART   ,
 	INSTALLMESSAGE_INSTALLEND     ,
 #endif // (_WIN32_MSI >= 450)
 } INSTALLMESSAGE;
enum _WIN32_MSI = 450; mixin((int _WIN32_MSI = _WIN32_MSI) { string r ="enum INSTALLMESSAGE { INSTALLMESSAGE_INITIALIZE, INSTALLMESSAGE_TERMINATE, INSTALLMESSAGE_SHOWDIALOG,"; if (_WIN32_MSI >= 500) r ~= "INSTALLMESSAGE_PERFORMANCE ,"; if (_WIN32_MSI >= 400) r ~= "INSTALLMESSAGE_RMFILESINUSE ,"; if (_WIN32_MSI >= 450) { r ~= "INSTALLMESSAGE_INSTALLSTART , INSTALLMESSAGE_INSTALLEND ,"; } return r ~ "}"; }()); ))) // sardonic laugh, which is not part of the source
Apr 27 2016
prev sibling parent reply Kagamin <spam here.lot> writes:
enum
{
// 12 others ...
	INSTALLMESSAGE_INITIALIZE     ,
	INSTALLMESSAGE_TERMINATE      ,
	INSTALLMESSAGE_SHOWDIALOG
}
static if(_WIN32_MSI >= 500)
enum INSTALLMESSAGE_PERFORMANCE=15;
static if(_WIN32_MSI >= 400)
enum INSTALLMESSAGE_RMFILESINUSE=16;
static if(_WIN32_MSI >= 450)
enum
{
	INSTALLMESSAGE_INSTALLSTART=17,
	INSTALLMESSAGE_INSTALLEND
}
Apr 28 2016
parent reply Jesse Phillips <Jesse.K.Phillips+D gmail.com> writes:
On Thursday, 28 April 2016 at 08:54:45 UTC, Kagamin wrote:
 enum
 {
 // 12 others ...
 	INSTALLMESSAGE_INITIALIZE     ,
 	INSTALLMESSAGE_TERMINATE      ,
 	INSTALLMESSAGE_SHOWDIALOG
 }
 static if(_WIN32_MSI >= 500)
 enum INSTALLMESSAGE_PERFORMANCE=15;
 static if(_WIN32_MSI >= 400)
 enum INSTALLMESSAGE_RMFILESINUSE=16;
 static if(_WIN32_MSI >= 450)
 enum
 {
 	INSTALLMESSAGE_INSTALLSTART=17,
 	INSTALLMESSAGE_INSTALLEND
 }
This one doesn't get the values right for the different versions. The other problem is functions are written as: void* something(INSTALLMESSAGE arg); So I could make all the functions take an int/uint or such, but that is a lot of change for the header along with less documenting.
Apr 28 2016
parent Kagamin <spam here.lot> writes:
On Thursday, 28 April 2016 at 22:54:10 UTC, Jesse Phillips wrote:
 This one doesn't get the values right for the different 
 versions. The other problem is functions are written as:

    void* something(INSTALLMESSAGE arg);

 So I could make all the functions take an int/uint or such, but 
 that is a lot of change for the header along with less 
 documenting.
Different values depending on target version? That's weird, never seen anything like that in windows headers. enum { // 12 others ... INSTALLMESSAGE_INITIALIZE , INSTALLMESSAGE_TERMINATE , INSTALLMESSAGE_SHOWDIALOG } static if(_WIN32_MSI >= 500) enum { INSTALLMESSAGE_PERFORMANCE=15, INSTALLMESSAGE_RMFILESINUSE } else static if(_WIN32_MSI >= 400) enum INSTALLMESSAGE_RMFILESINUSE=15; static if(_WIN32_MSI >= 450) enum { INSTALLMESSAGE_INSTALLSTART=INSTALLMESSAGE_RMFILESINUSE+1, INSTALLMESSAGE_INSTALLEND } alias INSTALLMESSAGE=int;
Apr 29 2016