TypedValue byte type being stored as int32?

When setting numeric attribute values in a dictionary, there are 5 types that can be used depending on the range of the number to be stored: byte, int16, int32, float, or double.

My assumption is that you would want to use the smallest type that your value will fit into in order to minimize file size. To test this, I created a model for each of the 5 numeric types and added a single dictionary with 10,000 attributes of the same type. For example, model-byte.skp has one attribute diction with 10,000 byte attributes set to the same value.

I had expected to see the file sizes increase in the order:

  • byte < int16 < int32 <= float < double

However, lookng at the file sizes on disk I see that the byte model is nearly as large as the float and int32 models:

175605 model-int16.skp
195577 model-byte.skp
195607 model-float.skp
195607 model-int32.skp
235607 model-double.skp

On further inspection when getting a value set as byte, the returned type says the value is an int32.

/// ...
SUTypedValueSetByte(typed_value, 65);
// ...
SUTypedValueGetType(typed_value, type_ptr) // returns the int32 type

It appears that byte types are actually being stored in the model as int32 types. Is this a bug?

This is a bug. I see that the C API takes a char is argument and pass that to the underlying C++ CTypedValue class. The setter overload that gets called is for int values. This is happening because the BYTE overload is unsigned char. To avoid loosing data the compiler will cast the char (signed) to int.

Exactly how CTypedValue is serialized I’m not entirely sure of. It’s a union type, so if it’s serialized by simply dumping its memory then it would be the size of the largest member. But seeing how you appear to get different sizes for other types I’m guessing that the current serialization is writing out a flag to indicate the type of the value and then the value itself. (But this is an implementation detail.)

But I assume fixing the setter for BYTE for SUTypedValue will address the file size difference you see.

It’s unfortunate the C API used char for the Get/Set of Byte - as Byte implies values of 0-255 and should be fit into unsigned char. (I’m more concerned about this though.) This means API users needs to cast their values to this function.

Logged bug as SUTypedValueSetByte sets int instead of byte · Issue #315 · SketchUp/api-issue-tracker · GitHub

I’d only use the smallest size which is applicable for the whole data set you store. I wouldn’t check each value and see what type it fits into.