Get data of internal data representation of primitive type

J

Jon Slaughter

Is there a way to collectively get the internal data for primitive types? So
for Int32, SByte, etc, I want to be able to get the byte stream used for the
data.

The reason is that I want a byte stream of the values but I don't want to
convert each one by hand(I started but its getting messy).

For, since double is a 64-bit type I'd like to get the actual bits in memory
so I can write them to a stream instead of converting the double to a byte
stream myself.

I'm thinking I'll probably have to use unsafe code and pointers but just
wanted to check and see if there was an easier way.

Thanks,
Jon
 
J

Jon Slaughter

Jon Slaughter said:
Is there a way to collectively get the internal data for primitive types?
So for Int32, SByte, etc, I want to be able to get the byte stream used
for the data.

The reason is that I want a byte stream of the values but I don't want to
convert each one by hand(I started but its getting messy).

For, since double is a 64-bit type I'd like to get the actual bits in
memory so I can write them to a stream instead of converting the double to
a byte stream myself.

I'm thinking I'll probably have to use unsafe code and pointers but just
wanted to check and see if there was an easier way.

Thanks,
Jon

What I came up with was

unsafe void WriteValueType(Stream s, ValueType v)

{

GCHandle h = GCHandle.Alloc(v, GCHandleType.Pinned);

Byte* b = (Byte*)h.AddrOfPinnedObject();

for (int i = 0; i < Marshal.SizeOf(v); i++)

s.WriteByte(*(b++));

h.Free();

}



which works and doesn't seem to bad. (I know very little of unsafe code
practices but it seems ok) I'm assuming that all value types hold contiguous
memory(well, that might not matter to much as I'm going to read the stream
the exact same way so it should be ok)
 
M

Marc Gravell

BitConverter.GetBytes(...) and BitConverter.To[...]() to get back the
primative.

but watch for BitConverter.IsLittleEndian - i.e. you might want to
know the endian-ness of your stream, otherwise it will go crazy if you
write on a Pentium etc (little-endian) and read on an Itanium (big-
endian). Jon Skeet has an EndianBitConverter than might help:
http://www.pobox.com/~skeet/csharp/miscutil/

Marc
 
J

Jon Slaughter

Marc Gravell said:
BitConverter.GetBytes(...) and BitConverter.To[...]() to get back the
primative.

but watch for BitConverter.IsLittleEndian - i.e. you might want to
know the endian-ness of your stream, otherwise it will go crazy if you
write on a Pentium etc (little-endian) and read on an Itanium (big-
endian). Jon Skeet has an EndianBitConverter than might help:
http://www.pobox.com/~skeet/csharp/miscutil/


Unfortunately I do not know the type that I am converting except that it is
a value type.
 
M

Marc Gravell

Ah; you stated <q>for primitive types</q>. As per a separate chain,
there is a big difference between a primative* type and a value-type.
You cannot serialize most value-types in the way you are trying. For
example: what does this contain?

public struct Pair
{
private readonly int value;
private readonly string name;
public int Value{ get { return value; } }
public string Name { get { return name; } }
public Pair(string name, int value)
{
this.name = name;
this.value = value;
}
}

The "value" is fine (just about), but the "name" is a reference. The
binary value is the /address/ of the string; serializing a memory
address is always** a bug. As an aside, the size of the address will
itself change between 32-bit and 64-bit.
Likewise, this could be *any* reference-type, not just string; for
example:

KeyValuePair<Stream, Form>

is a perfectly well defined struct...

Now - you could argue that you only want to serialize structs that are
only composed of structs, but the reality is that string is so
important that this is not going to be all that useful...

*: by this I'm meaning the predefined types as per section 8.2.1 of
ECMA 334
**: unless you're writing a debugger!
 
M

Marc Gravell

I said> a big difference between a primative* type and a value-type

Before things get confusing; can I clarify: I mean that the predefined
types are a small subset of value-types; i.e. an int (or Int32) *is* a
value-type; I don't mean that they are mutually exclusive terms.

Marc
 
J

Jon Slaughter

Marc Gravell said:
I said> a big difference between a primative* type and a value-type

Before things get confusing; can I clarify: I mean that the predefined
types are a small subset of value-types; i.e. an int (or Int32) *is* a
value-type; I don't mean that they are mutually exclusive terms.

Not sure what your talking about. My write code just recurses over all
types. If its a value type then I write it out to file, else its either a
field or property. (I guess it could be an object which I haven't handled)

The problem, so far at least, is not writing out the structure as I have
done this for some simple ones(and it should work for arbitrary ones I
imagine) but reading them in. I'm having problems reading in arrays because
I must allocate them of the proper type(which I can't because I can't do
dynamic casts ;/).

if (val is Array)
{
object numo = (Int32)0;
ReadValueType(stream, numo);
object[] v = new object[(Int32)numo];
for (int i = 0; i < (Int32)numo; i++)
{
this.DeserializeSub(stream, ref v);
}
val = v;
return true;
}

that is my code right now to handle an array. It doesn't work cause ref v
is an object and not of the proper type(which you can get from the type
parameter from the class(its generic)).

so for example I know what type val contains cause I use the generic type as
a guide which lets me "look" at the types in the class. But because I cannot
cast v dynamically into the proper type I can't do much ;/

for example, in my test code, when I break on the first line(object numo),

val is type object {int[]}

so I need to create v to mimic it and then I would have no issues ;/

I have no clue how to do this though or if its possible.

(basically if val is an array of value types then Deserializesub will get it
and store it in the second parameter.)

Don't know if I'm at a dead end or not though ;/ Would be nice if I could do
somethign like

val.ElementType[] v = new val.ElementType[(Int32)numo]; so that the proper
type can be passed to DeserializeSub. I might be able to modify
DeserializeSub and pass the type in another parameter but it probably will
just end up making a mess.

Jon
 
M

Marc Gravell

Not sure what your talking about. My write code just recurses over all
types. If its a value type then I write it out to file, else its either a
field or property.
??? value-type vs reference-type relates to types; field vs property
relates to members... it can be a value-type *and* a field or property
member...
(and it should work for arbitrary ones I imagine)
I disagree; "arbitrary" has to include reference-types, which you
aren't considering.
but it probably will just end up making a mess.
I'm thinking you already got there... sorry, but I *really* think
you're deeply over your head here. Custom serialization *of arbitrary
types* is not trivial. I'm not even going to /begin/ to unpick that
code, especially with the unsafe hacks. Serializing your own known
type (from the inside) is fair enough; implement ISerializable and the
custom ctor - job done. But before trying to out-do the serializer, I
would want to *know* that the regular serialization engine isn't good
enough (i.e. have a definition of "good enough"). I'm not convinced
that this is going to be worth the development / support cost... I'd
look at simply zipping what you have, picking either xml or binary
serialization as most appropriate, and trying a few different
compression algorithms (gzip, deflate, bzip2, etc), perhaps from a few
providers (ms, #ziplib, etc). That would take, at worst, 20 minutes.
With zero ongoing cost.

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top