Thread overview
Using the Variant (Setting it's memory location)
Feb 05, 2012
Era Scarecrow
Feb 06, 2012
Ali Çehreli
Feb 06, 2012
Era Scarecrow
Feb 06, 2012
Jesse Phillips
Feb 07, 2012
Era Scarecrow
Feb 07, 2012
Jesse Phillips
Feb 07, 2012
Pedro Lacerda
Feb 08, 2012
Era Scarecrow
Feb 08, 2012
Pedro Lacerda
February 05, 2012
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);
February 06, 2012
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
February 06, 2012
> 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...
February 06, 2012
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()
February 07, 2012
> 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.
February 07, 2012
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.
February 07, 2012
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.
>


February 08, 2012
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
}
February 08, 2012
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
> }
>