vfs: check userland buffers before reading them.
[haiku.git] / src / libs / icon / flat_icon / FlatIconFormat.cpp
blobeb5d4679ce5ca026be340fab7d3847f9d150558b
1 /*
2 * Copyright 2006-2007, Haiku. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Stephan Aßmus <superstippi@gmx.de>
7 */
10 #include "FlatIconFormat.h"
12 #include "LittleEndianBuffer.h"
15 _BEGIN_ICON_NAMESPACE
18 const uint32 FLAT_ICON_MAGIC = 'ficn';
20 const char* kVectorAttrNodeName = "BEOS:ICON";
21 const char* kVectorAttrMimeName = "META:ICON";
24 // read_coord
25 bool
26 read_coord(LittleEndianBuffer& buffer, float& coord)
28 uint8 value;
29 if (!buffer.Read(value))
30 return false;
32 if (value & 128) {
33 // high bit set, the next byte is part of the coord
34 uint8 lowValue;
35 if (!buffer.Read(lowValue))
36 return false;
37 value &= 127;
38 uint16 coordValue = (value << 8) | lowValue;
39 coord = (float)coordValue / 102.0 - 128.0;
40 } else {
41 // simple coord
42 coord = (float)value - 32.0;
44 return true;
47 // write_coord
48 bool
49 write_coord(LittleEndianBuffer& buffer, float coord)
51 // clamp coord
52 if (coord < -128.0)
53 coord = -128.0;
54 if (coord > 192.0)
55 coord = 192.0;
57 if (int(coord * 100.0) == (int)coord * 100
58 && coord >= - 32.0 && coord <= 95.0) {
59 // saving coord in 7 bit is sufficient
60 uint8 value = (uint8)(coord + 32.0);
61 return buffer.Write(value);
62 } else {
63 // needing to save coord in 15 bits
64 uint16 value = (uint16)((coord + 128.0) * 102.0);
65 // set high bit to indicate there is only one byte
66 value |= 32768;
67 uint8 highValue = value >> 8;
68 uint8 lowValue = value & 255;
69 return buffer.Write(highValue) && buffer.Write(lowValue);
73 // read_float_24
74 bool
75 read_float_24(LittleEndianBuffer& buffer, float& _value)
77 uint8 bufferValue[3];
78 if (!buffer.Read(bufferValue[0]) || !buffer.Read(bufferValue[1])
79 || !buffer.Read(bufferValue[2]))
80 return false;
82 int shortValue = (bufferValue[0] << 16)
83 | (bufferValue[1] << 8) | bufferValue[2];
85 int sign = (shortValue & 0x800000) >> 23;
86 int exponent = ((shortValue & 0x7e0000) >> 17) - 32;
87 int mantissa = (shortValue & 0x01ffff) << 6;
89 if (shortValue == 0)
90 _value = 0.0;
91 else {
92 uint32 value = (sign << 31) | ((exponent + 127) << 23) | mantissa;
94 _value = (float&)value;
97 return true;
100 // write_float_24
101 bool
102 write_float_24(LittleEndianBuffer& buffer, float _value)
104 // 1 bit sign
105 // 6 bit exponent
106 // 17 bit mantissa
107 // TODO: fixme for non-IEEE 754 architectures
108 uint32 value = (uint32&)_value;
110 int sign = (value & 0x80000000) >> 31;
111 int exponent = ((value & 0x7f800000) >> 23) - 127;
112 int mantissa = value & 0x007fffff;
114 if (exponent >= 32 || exponent < -32) {
115 uint8 zero = 0;
116 return buffer.Write(zero) && buffer.Write(zero)
117 && buffer.Write(zero);
120 int shortValue = (sign << 23)
121 | ((exponent + 32) << 17)
122 | (mantissa >> 6);
124 return buffer.Write((uint8)(shortValue >> 16))
125 && buffer.Write((uint8)((shortValue >> 8) & 0xff))
126 && buffer.Write((uint8)(shortValue & 0xff));
130 _END_ICON_NAMESPACE