View mode: basic / threaded / horizontal-split · Log in · Help
January 26, 2007
4-character literal
Hi. I'm porting some Mac OS X (Carbon) code, and it relies heavily on a language feature that's been used on the Mac for decades: 4-byte character literals (like 'abcd'). In this case, I'm setting up enums that will be passed to OS APIs as 32-bit unsigned int parameters:

enum : uint
{
   kSomeConstantValue = 'abcd'
}

I tried using a 4-character string literal, but I get the following error when I do:

src/d/macos/carbon/carbonevents.d:29: Error: cannot implicitly convert expression ("ptrg") of type char[4] to uint
src/d/macos/carbon/carbonevents.d:29: Error: Integer constant expression expected instead of cast(uint)"ptrg"
src/d/macos/carbon/carbonevents.d:34: Error: cannot implicitly convert expression ("etrg") of type char[4] to uint
src/d/macos/carbon/carbonevents.d:34: Error: Integer constant expression expected instead of cast(uint)"etrg"


I tried basing the enum on dchar, and I tried appending "d" to the end of the string literals, but neither works.

Any suggestions that don't involve significant re-writing of the 4-character literals? Thanks!


P.S. Grr. I don't like posting my unobfuscated email address to public sites.
January 26, 2007
Re: 4-character literal
Rick Mann Wrote:

> enum : uint
> {
>     kSomeConstantValue = 'abcd'
> }


I realized I was misunderstanding something else I saw, and that "abcd"d doesn't do what I thought (make a 4-byte character).

So: how to I do the equivalent of 'abcd'?

Thanks!
January 26, 2007
Re: 4-character literal
Rick Mann wrote:
> Rick Mann Wrote:
> 
> 
>>enum : uint
>>{
>>    kSomeConstantValue = 'abcd'
>>}
> 
> 
> 
> I realized I was misunderstanding something else I saw, and that "abcd"d doesn't do what I thought (make a 4-byte character).
> 
> So: how to I do the equivalent of 'abcd'?
> 
> Thanks!

Two solutions come to mind:

1) Will work, very ugly:
(cast(uint) 'a' << 24) + (cast(uint) 'b' << 16) + (cast(uint) 'c' << 8) 
+ cast(uint) 'd'

2) Probably won't work:
*(cast(uint*) ("abcd".ptr))

3) Will work:
0x61626364

Each pretty bad. IMHO the original solution is pretty bad too :)

 - Gregor Richards
January 26, 2007
Re: 4-character literal
Rick Mann wrote:
> Rick Mann Wrote:
> 
>> enum : uint
>> {
>>     kSomeConstantValue = 'abcd'
>> }
> 
> 
> I realized I was misunderstanding something else I saw, and that "abcd"d doesn't do what I thought (make a 4-byte character).
> 
> So: how to I do the equivalent of 'abcd'?
> 
> Thanks!

Try this.

template MAKE_ID(char[] s)
{
    static assert(s.length == 4);
    const uint ID = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
}

enum : uint
{
    kSomeConstantValue = MAKE_ID!("abcd")
}
January 26, 2007
Re: 4-character literal
torhu wrote:
> Rick Mann wrote:
>> Rick Mann Wrote:
>> 
>>> enum : uint
>>> {
>>>     kSomeConstantValue = 'abcd'
>>> }
>> 
>> 
>> I realized I was misunderstanding something else I saw, and that "abcd"d doesn't do what I thought (make a 4-byte character).
>> 
>> So: how to I do the equivalent of 'abcd'?
>> 
>> Thanks!
> 
> Try this.
> 
> template MAKE_ID(char[] s)
> {
>      static assert(s.length == 4);
>      const uint ID = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
> }
> 
> enum : uint
> {
>      kSomeConstantValue = MAKE_ID!("abcd")
> }

Seems I was too quick.  Replace 'const uint ID' with 'const uint 
MAKE_ID', and it will compile.
January 26, 2007
Re: 4-character literal
Rick Mann wrote:
> Rick Mann Wrote:
> 
>> enum : uint
>> {
>>     kSomeConstantValue = 'abcd'
>> }
> 
> 
> I realized I was misunderstanding something else I saw, and that "abcd"d doesn't do what I thought (make a 4-byte character).
> 
> So: how to I do the equivalent of 'abcd'?
> 
> Thanks!


To add to Gregor Richards suggestions, you may try an union (untested).

union Converter { uint asInt; char[4] chr; }
const Converter kSomeConstantValue = { chr : "abcd" };

//To get
kSomeConstantValue.asInt

-Joel
January 26, 2007
Re: 4-character literal
Rick Mann wrote:
> Rick Mann Wrote:
> 
>> enum : uint
>> {
>>     kSomeConstantValue = 'abcd'
>> }
> 
> 
> I realized I was misunderstanding something else I saw, and that "abcd"d doesn't do what I thought (make a 4-byte character).
> 
> So: how to I do the equivalent of 'abcd'?
> 
> Thanks!

Interesting question.  How's this?

import std.stdio;

template touint(char[] T)
{
    static assert(T.length==4, "Integer constants must be of length 4");
    const uint touint =
        (cast(char)T[0] << 24)|
        (cast(char)T[1] << 16)|
        (cast(char)T[2] << 8)|
        (cast(char)T[3]);
}

enum
{
    kSomeConstantValue = touint!("xyzz")
}

void main()
{
    writefln("%x", kSomeConstantValue);
}
January 26, 2007
Re: 4-character literal
Bill Baxter wrote:
> Rick Mann wrote:
>> Rick Mann Wrote:
>>
>>> enum : uint
>>> {
>>>     kSomeConstantValue = 'abcd'
>>> }
>>
>>
>> I realized I was misunderstanding something else I saw, and that 
>> "abcd"d doesn't do what I thought (make a 4-byte character).
>>
>> So: how to I do the equivalent of 'abcd'?
>>
>> Thanks!
> 
> Interesting question.  How's this?
> 
> import std.stdio;
> 
> template touint(char[] T)
> {
>     static assert(T.length==4, "Integer constants must be of length 4");
>     const uint touint =
>         (cast(char)T[0] << 24)|
>         (cast(char)T[1] << 16)|
>         (cast(char)T[2] << 8)|
>         (cast(char)T[3]);
> }
> 
> enum
> {
>     kSomeConstantValue = touint!("xyzz")
> }
> 
> void main()
> {
>     writefln("%x", kSomeConstantValue);
> }
> 

Damn!  Torhu beat me too it!

--bb
January 26, 2007
Re: 4-character literal
torhu Wrote:

> Try this.
> 
> template MAKE_ID(char[] s)
> {
>      static assert(s.length == 4);
>      const uint ID = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
> }
> 
> enum : uint
> {
>      kSomeConstantValue = MAKE_ID!("abcd")
> }

Of the solutions proposed so far, this is probably the cleanest. Thanks!

Sadly, nothing's really as nice as just saying 'abcd'. What would it take to get multi-character literals added to the language?
January 26, 2007
Re: 4-character literal
Rick Mann wrote:
> torhu Wrote:
> 
>> Try this.
>>
>> template MAKE_ID(char[] s)
>> {
>>      static assert(s.length == 4);
>>      const uint ID = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
>> }
>>
>> enum : uint
>> {
>>      kSomeConstantValue = MAKE_ID!("abcd")
>> }
> 
> Of the solutions proposed so far, this is probably the cleanest. Thanks!
> 
> Sadly, nothing's really as nice as just saying 'abcd'. What would it take to get multi-character literals added to the language?
> 

In general, I don't think it could work in a useful way. 4-character 
literals do not fit in a uint. It only really works for ASCII.
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home