Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
February 05, 2012 Using the Variant (Setting it's memory location) | ||||
---|---|---|---|---|
| ||||
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 Re: Using the Variant (Setting it's memory location) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Era Scarecrow | 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 Re: Using the Variant (Setting it's memory location) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | > 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 Re: Using the Variant (Setting it's memory location) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Era Scarecrow | 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 Re: Using the Variant (Setting it's memory location) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips | > 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 Re: Using the Variant (Setting it's memory location) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Era Scarecrow | 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 Re: Using the Variant (Setting it's memory location) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jesse Phillips Attachments:
| 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 Re: Using the Variant (Setting it's memory location) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Pedro Lacerda | 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 Re: Using the Variant (Setting it's memory location) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Era Scarecrow Attachments:
| 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
> }
>
|
Copyright © 1999-2021 by the D Language Foundation