www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Using the Variant (Setting it's memory location)

reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
I've been working and building a struct called 'AllTypes' which 
I've come to the conclusion is already available as a variant. 
However as I look at the documentation I don't see any 
methods/constructors to use where I can specify where I want the 
data to be access from.

The data I will be accessing has dozens of different structures 
of records which I keep the formatting and types saved in an 
array. I see the problem where although variant can handle what I 
need, but I don't see a way to specify a specific memory 
range/access in order to use it.

ubyte[] buffer;

//buffer is loaded at some point with data so length > 0;
buffer.length = 2;

//0 is the offset from the buffer rather than making a range.
Variant v(buffer, int8, 0);
v = 10;
assert(buffer[0] == 10);

v = Variant(buffer, int8, 1);
v = 25;

assert(buffer[0] == 10);
assert(buffer[1] == 25);
Feb 05 2012
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 02/05/2012 12:20 PM, Era Scarecrow wrote:
 I've been working and building a struct called 'AllTypes' which I've
 come to the conclusion is already available as a variant. However as I
 look at the documentation I don't see any methods/constructors to use
 where I can specify where I want the data to be access from.

 The data I will be accessing has dozens of different structures of
 records which I keep the formatting and types saved in an array. I see
 the problem where although variant can handle what I need, but I don't
 see a way to specify a specific memory range/access in order to use it.

 ubyte[] buffer;

 //buffer is loaded at some point with data so length > 0;
 buffer.length = 2;

 //0 is the offset from the buffer rather than making a range.
 Variant v(buffer, int8, 0);
 v = 10;
 assert(buffer[0] == 10);

 v = Variant(buffer, int8, 1);
 v = 25;

 assert(buffer[0] == 10);
 assert(buffer[1] == 25);
I see that it's not exactly what you are looking for, but have you looked at std.conv.emplace()? Ali
Feb 05 2012
parent "Era Scarecrow" <rtcvb32 yahoo.com> writes:
 I see that it's not exactly what you are looking for, but have 
 you looked at std.conv.emplace()?
I've glanced it over, and I don't understand it, but it also doesn't quite seem right. I know sometimes I'll know what the type and size is, but most of the time only my array of data will tell me. I can likely handle it all in the type I was making, or a switch case. I was just hoping to avoid that if I could. the structure of the data can sometimes be something like (int, int, int, float, float, float, char[1], char[3], char[32]). Wow... serious case of Déjà vu...
Feb 06 2012
prev sibling parent reply "Jesse Phillips" <jessekphillips+D gmail.com> writes:
On Sunday, 5 February 2012 at 20:20:58 UTC, Era Scarecrow wrote:
 The data I will be accessing has dozens of different structures 
 of records which I keep the formatting and types saved in an 
 array. I see the problem where although variant can handle what 
 I need, but I don't see a way to specify a specific memory 
 range/access in order to use it.
Variant allows you to store any value, but it does not need a buffer or have interaction like an array. It can hold any value because it the size of the data structure is the max size of the times it can hold. For this reason it can not actually hold any structure. For an array of any values you use a Variant[] foo = new Variant[100]. foo[0] = myInt; foo[1] = myFloat; However depending on the length of char[static size], you may need to give Variant a larger maximum size. VariantN!(mySize)[]... You can also use the Algebraic type to specified allowed types: Algebraic!(int,float,char[3],char[100]...)[]... This will calculate the max size you need and only allow those times to be assigned. Accessing is different. The Variant type does not convert to any type, so you must know the type or ask if it is a type. foo.get!int() if(foo[0].type == int) // I think that was valid check. Maybe typeid(int) foo[0].get!int()
Feb 06 2012
parent reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
 Variant allows you to store any value, but it does not need a 
 buffer or have interaction like an array. It can hold any value 
 because it the size of the data structure is the max size of 
 the times it can hold. For this reason it can not actually hold 
 any structure.

 For an array of any values you use a Variant[] foo = new 
 Variant[100].

 foo[0] = myInt;
 foo[1] = myFloat;

 However depending on the length of char[static size], you may 
 need to give Variant a larger maximum size.
Unfortunately I'd need to reference a buffer for the known structured types. Variant seems far more useful for making an interpreted language, than for my purposes. I'll just have to simplify the access/reading/writing structures to basically doing just that (Drop any compare and added complexity), and use native data types to handle and work with the data.
Feb 06 2012
parent reply "Jesse Phillips" <jessekphillips+D gmail.com> writes:
On Tuesday, 7 February 2012 at 00:39:00 UTC, Era Scarecrow wrote:
 Unfortunately I'd need to reference a buffer for the known 
 structured types. Variant seems far more useful for making an 
 interpreted language, than for my purposes.
I've been using Variant with LuaD for some time. Sorry it isn't what you need but hopefully you'll know when it will be useful.
Feb 07 2012
parent reply Pedro Lacerda <pslacerda gmail.com> writes:
You can roll your own tagged union instead. The S struct can store long and
byte[], S.ptr is a pointer to the data.

    enum Type { Long, Bytes }
    struct S {
        Type type;
        void* ptr;
        union {
            long _long;
            byte[] _bytes;
        }
        this(long l) {
            _long = l;
            type = Type.Long;
            ptr = &_long;
        }
        this(byte[] bytes) {
            _bytes = bytes;
            type = Type.Bytes;
            ptr = &_long;
        }
    }

    auto s = S(99);
    assert(s.ptr == &(s._long));
    assert(s.ptr == &(s._bytes));

Pedro Lacerda



2012/2/7 Jesse Phillips <jessekphillips+D gmail.com>

 On Tuesday, 7 February 2012 at 00:39:00 UTC, Era Scarecrow wrote:

 Unfortunately I'd need to reference a buffer for the known structured
 types. Variant seems far more useful for making an interpreted language,
 than for my purposes.
I've been using Variant with LuaD for some time. Sorry it isn't what you need but hopefully you'll know when it will be useful.
Feb 07 2012
parent reply "Era Scarecrow" <rtcvb32 yahoo.com> writes:
On Tuesday, 7 February 2012 at 17:51:42 UTC, Pedro Lacerda wrote:
 You can roll your own tagged union instead. The S struct can 
 store long and
 byte[], S.ptr is a pointer to the data.
Yep, a bit like my code, except with switch cases covering all major types; That and trying to do comparison and setting functions, which seems a bit much. Testing it using templates and testing all the types seems like a nightmare. I've decided I need to pass it a ubyte array so I could do bounds checking before binding the memory to the union. One fewer things to worry about. Let's see... not that I expect you to use this, but I sorta have this as my enum set for types. enum ValueType { raw = 0x00000000, ///default upon unknown mask_types = 0xfff00000, ///Upper 4k defines general types, or 12 flag types mask_size = 0x000fffff, ///lower gives 1Million for size. i_types = 0x00100000, ///integars types i_8 = i_types + byte.sizeof, i_16 = i_types + short.sizeof, i_32 = i_types + int.sizeof, i_64 = i_types + long.sizeof, u_types = 0x00200000, ///unsigned numbers u_8 = u_types + ubyte.sizeof, u_16 = u_types + ushort.sizeof, u_32 = u_types + uint.sizeof, u_64 = u_types + ulong.sizeof, floating_types = 0x00400000, float_32 = floating_types + float.sizeof, fl = float_32, double_64 = floating_types + double.sizeof, doub = double_64, flags_types = 0x00800000, flags_8 = flags_types + ubyte.sizeof, flags_16 = flags_types + ushort.sizeof, flags_32 = flags_types + uint.sizeof, flags_64 = flags_types + ulong.sizeof, ranged_types = 0x01000000, ranged_8 = ranged_types + ubyte.sizeof, ranged_16 = ranged_types + ushort.sizeof, ranged_32 = ranged_types + uint.sizeof, ranged_64 = ranged_types + ulong.sizeof, voidp = 0x02000000, pointer_types = voidp, ///pointers i_8p, u_8p, i_16p, u_16p, i_32p, u_32p, i_64p, u_64p, float_32p, double_64p, var_str = 0x04000000, fixed_str = 0x08000000, var_ustr = 0x10000000, fixed_ustr = 0x20000000 }
Feb 08 2012
parent Pedro Lacerda <pslacerda gmail.com> writes:
Umm, sounds nice. If you want to store a long into buffer, you can cast the
desired position as long* and assign the value. The following is adapted
from std.outbuffer, that is another option.

    ubyte buffer[];
    size_t offset;

    ulong a = 1;
    byte b = 2;

    // allocate space for ulong e byte
    buffer.length = a.sizeof + b.sizeof;

    *cast(ulong *)&buffer[offset] = a; // store value
    offset += a.sizeof;                // increment offset

    *cast(byte *)&buffer[offset] = b;
    offset += b.sizeof;


Pedro Lacerda



2012/2/8 Era Scarecrow <rtcvb32 yahoo.com>

 On Tuesday, 7 February 2012 at 17:51:42 UTC, Pedro Lacerda wrote:

 You can roll your own tagged union instead. The S struct can store long
 and
 byte[], S.ptr is a pointer to the data.
Yep, a bit like my code, except with switch cases covering all major types; That and trying to do comparison and setting functions, which seems a bit much. Testing it using templates and testing all the types seems like a nightmare. I've decided I need to pass it a ubyte array so I could do bounds checking before binding the memory to the union. One fewer things to worry about. Let's see... not that I expect you to use this, but I sorta have this as my enum set for types. enum ValueType { raw = 0x00000000, ///default upon unknown mask_types = 0xfff00000, ///Upper 4k defines general types, or 12 flag types mask_size = 0x000fffff, ///lower gives 1Million for size. i_types = 0x00100000, ///integars types i_8 = i_types + byte.sizeof, i_16 = i_types + short.sizeof, i_32 = i_types + int.sizeof, i_64 = i_types + long.sizeof, u_types = 0x00200000, ///unsigned numbers u_8 = u_types + ubyte.sizeof, u_16 = u_types + ushort.sizeof, u_32 = u_types + uint.sizeof, u_64 = u_types + ulong.sizeof, floating_types = 0x00400000, float_32 = floating_types + float.sizeof, fl = float_32, double_64 = floating_types + double.sizeof, doub = double_64, flags_types = 0x00800000, flags_8 = flags_types + ubyte.sizeof, flags_16 = flags_types + ushort.sizeof, flags_32 = flags_types + uint.sizeof, flags_64 = flags_types + ulong.sizeof, ranged_types = 0x01000000, ranged_8 = ranged_types + ubyte.sizeof, ranged_16 = ranged_types + ushort.sizeof, ranged_32 = ranged_types + uint.sizeof, ranged_64 = ranged_types + ulong.sizeof, voidp = 0x02000000, pointer_types = voidp, ///pointers i_8p, u_8p, i_16p, u_16p, i_32p, u_32p, i_64p, u_64p, float_32p, double_64p, var_str = 0x04000000, fixed_str = 0x08000000, var_ustr = 0x10000000, fixed_ustr = 0x20000000 }
Feb 08 2012