www.digitalmars.com         C & C++   DMDScript  

D - Registry API: Null values

reply "Matthew Wilson" <matthew stlsoft.org> writes:
Am interested in everyone's thoughts about how to handle keys without
values, ie. what to return when calling get_Value(NULL) or get_Value("") for
keys that do not have a value.

The options are:

1. Return a null reference for the Value
2. Return a Value whose name is null, and whose type is REG_NONE (0).
3. Return a Value whose name is the empty string, and whose type is REG_NONE
(0).
4. Throw an exception.

I'm not keen on throwing an exception, not really on having nulls around the
place, so it's currently option 3. I can't say I'm in love with it, but it
seems to me to be the best, since it is definitive (Value.get_Type() returns
REG_NONE) and non-null-weilding (so it's harmless to pass the "name" to
things expecting a non-null string).

Thoughts appreciated.

Matthew

P.S. Walter, still hanging out for those properties ...
Sep 13 2003
next sibling parent reply "Matthew Wilson" <matthew stlsoft.org> writes:
Hmm, how about

5. Key.get_Value() returns a Value, which returns REG_NONE for
Value.get_Type(), but throws an exception if any of the get_Value_DWORD(),
get_Value_MULTI_SZ() etc. methods are called.

I think that's probably the best. (Still interested in all your opinions
though, :) )

Matthew


"Matthew Wilson" <matthew stlsoft.org> wrote in message
news:bk0udu$b38$1 digitaldaemon.com...
 Am interested in everyone's thoughts about how to handle keys without
 values, ie. what to return when calling get_Value(NULL) or get_Value("")
for
 keys that do not have a value.

 The options are:

 1. Return a null reference for the Value
 2. Return a Value whose name is null, and whose type is REG_NONE (0).
 3. Return a Value whose name is the empty string, and whose type is
REG_NONE
 (0).
 4. Throw an exception.

 I'm not keen on throwing an exception, not really on having nulls around
the
 place, so it's currently option 3. I can't say I'm in love with it, but it
 seems to me to be the best, since it is definitive (Value.get_Type()
returns
 REG_NONE) and non-null-weilding (so it's harmless to pass the "name" to
 things expecting a non-null string).

 Thoughts appreciated.

 Matthew

 P.S. Walter, still hanging out for those properties ...
Sep 13 2003
next sibling parent reply Patrick Down <pat codemoon.com> writes:
"Matthew Wilson" <matthew stlsoft.org> wrote in
news:bk0unb$bcj$1 digitaldaemon.com: 

 Hmm, how about
 
 5. Key.get_Value() returns a Value, which returns REG_NONE for
 Value.get_Type(), but throws an exception if any of the
 get_Value_DWORD(), get_Value_MULTI_SZ() etc. methods are called.
 
 I think that's probably the best. (Still interested in all your
 opinions though, :) )
I like this one too. What do you do when some asks for DWORD and the actual type is string?
Sep 14 2003
parent "Matthew Wilson" <matthew stlsoft.org> writes:
I throw a RegistryException, as in:


private void Key_QueryValue(in HKEY hkey, in char[] name, out uint value,
out REG_VALUE_TYPE type)
{
//printf("Key_QueryValue(uint)\n");

    DWORD   cbData  =   value.size;
    LONG    res     =   RegQueryValueExA(hkey, name, (Reserved)0, type,
&value, cbData);

    if(0 != res)
    {
        throw new RegistryException("Cannot read the requested value", res);
    }
    else
    {
        switch(type)
        {
            default:
                throw new RegistryException("Cannot read the given value as
a 32-bit integer");
                break;
version(LittleEndian)
{
            case    REG_VALUE_TYPE.REG_DWORD_LITTLE_ENDIAN:
                assert(REG_VALUE_TYPE.REG_DWORD ==
REG_VALUE_TYPE.REG_DWORD_LITTLE_ENDIAN);
                break;
            case    REG_VALUE_TYPE.REG_DWORD_BIG_ENDIAN:
} // version(LittleEndian)
version(BigEndian)
{
            case    REG_VALUE_TYPE.REG_DWORD_BIG_ENDIAN:
                assert(REG_VALUE_TYPE.REG_DWORD ==
REG_VALUE_TYPE.REG_DWORD_BIG_ENDIAN);
                break;
            case    REG_VALUE_TYPE.REG_DWORD_LITTLE_ENDIAN:
} // version(BigEndian)
                value = swap(value);
                break;
        }
    }
}

class Value
{
    . . .

    uint get_Value_DWORD()
    {
        REG_VALUE_TYPE  type;
        uint            value;

        Key_QueryValue(m_key.m_hkey, m_name, value, type);

        if(type != m_type)
        {
            throw new RegistryException("Value type has been changed since
the value was acquired");
        }

        return value;
    }

However, the same is not true in the other direction. If the type is
convertible to a string form, then that is done (swapping around the
endian-ness as necessary). Hence the types that are implicitly converted to
string are REG_SZ, REG_EXPAND_SZ, REG_DWORD*, REG_QWORD*. REG_BINARY and
REG_MULTI_SZ are not converted, and an exception is thrown.

REG_RESOURCE_LIST, REG_FULL_RESOURCE_DESCRIPTOR and
REG_RESOURCE_REQUIREMENTS_LIST are not supported in any form at this time.

Note that "Value" instances contain name, Key reference and type. Hence,
when a Value's value is acquired, it is conceivable that another process may
have deleted the existing value and created another with a different type.
Hence, the get_Value_*() methods throw an exception if that's happened. It's
not perfect, of course, but since client code is going to be wanting to
dispatch on type - Value.get_Type() - we need to catch the possible external
breaking changes. The alternative is to just know nothing about a type, and
get its type each time get_Type() is called. If anyone's got any firm
opinions either way, this'd be a good time to hear them. :)

Matthew


"Patrick Down" <pat codemoon.com> wrote in message
news:Xns93F662E5C3ACEpatcodemooncom 63.105.9.61...
 "Matthew Wilson" <matthew stlsoft.org> wrote in
 news:bk0unb$bcj$1 digitaldaemon.com:

 Hmm, how about

 5. Key.get_Value() returns a Value, which returns REG_NONE for
 Value.get_Type(), but throws an exception if any of the
 get_Value_DWORD(), get_Value_MULTI_SZ() etc. methods are called.

 I think that's probably the best. (Still interested in all your
 opinions though, :) )
I like this one too. What do you do when some asks for DWORD and the actual type is string?
Sep 14 2003
prev sibling parent reply "Riccardo De Agostini" <riccardo.de.agostini email.it> writes:
"Matthew Wilson" <matthew stlsoft.org> ha scritto nel messaggio
news:bk0unb$bcj$1 digitaldaemon.com...
 Hmm, how about

 5. Key.get_Value() returns a Value, which returns REG_NONE for
 Value.get_Type(), but throws an exception if any of the get_Value_DWORD(),
 get_Value_MULTI_SZ() etc. methods are called.

 I think that's probably the best. (Still interested in all your opinions
 though, :) )
Perfectly consistent, no nulls hanging around, and doesn't throw exceptions unless needed. Go for it! Ric
Sep 15 2003
parent "Matthew Wilson" <matthew stlsoft.org> writes:
Am glad you like. The first version - read-only/enumeration - is just about
ready. I am hoping to deploy in the next few hours.

:)

"Riccardo De Agostini" <riccardo.de.agostini email.it> wrote in message
news:bk429e$1gi5$12 digitaldaemon.com...
 "Matthew Wilson" <matthew stlsoft.org> ha scritto nel messaggio
 news:bk0unb$bcj$1 digitaldaemon.com...
 Hmm, how about

 5. Key.get_Value() returns a Value, which returns REG_NONE for
 Value.get_Type(), but throws an exception if any of the
get_Value_DWORD(),
 get_Value_MULTI_SZ() etc. methods are called.

 I think that's probably the best. (Still interested in all your opinions
 though, :) )
Perfectly consistent, no nulls hanging around, and doesn't throw
exceptions
 unless needed. Go for it!

 Ric
Sep 15 2003
prev sibling parent Andy Friesen <andy ikagames.com> writes:
Matthew Wilson wrote:

 Am interested in everyone's thoughts about how to handle keys without
 values, ie. what to return when calling get_Value(NULL) or get_Value("") for
 keys that do not have a value.
 
 The options are:
 
 1. Return a null reference for the Value
 2. Return a Value whose name is null, and whose type is REG_NONE (0).
 3. Return a Value whose name is the empty string, and whose type is REG_NONE
 (0).
 4. Throw an exception.
Python dictionaries offer all of the above. The [] operator raises a ValueError if the key does not exist, and the get(keyName, default) method will return the default should the key not exist. (such as null) This does mean more methods that do nearly the same thing, but I find that the extra bit of sugar really does make the interface a lot easier to work with. -- andy
Sep 13 2003