11006:位域样式的可移植编码
题目
把位域结构表示的文本样式编码为布局固定的 32 位无符号整数,并完成反向解码。交换格式不得依赖位域的对象表示。
解析
位域适合表达字段含义,但字段排列顺序、填充方式和结构体大小都可能随实现变化。因此,编码时应逐个读取字段,再用掩码和移位构造数值;解码时也应从数值中逐段提取字段。
两个函数都先完成全部检查和计算,最后才写入输出对象。这样,保留位、字号或对齐方式非法时,调用方原有结果不会被部分覆盖。
解析
c
#include <stdbool.h>
#include <stdint.h>
enum {
TEXT_ALIGN_LEFT = 0,
TEXT_ALIGN_CENTER = 1,
TEXT_ALIGN_RIGHT = 2
};
typedef struct {
unsigned int font_id : 8;
unsigned int size : 7;
unsigned int alignment : 2;
unsigned int bold : 1;
unsigned int italic : 1;
unsigned int underline : 1;
} TextStyle;
bool text_style_encode(
const TextStyle *style,
uint32_t *out_code
);
bool text_style_decode(
uint32_t code,
TextStyle *out_style
);
enum {
FONT_ID_SHIFT = 0,
SIZE_SHIFT = 8,
ALIGNMENT_SHIFT = 15,
BOLD_SHIFT = 17,
ITALIC_SHIFT = 18,
UNDERLINE_SHIFT = 19
};
static const uint32_t FONT_ID_MASK = UINT32_C(0xff);
static const uint32_t SIZE_MASK = UINT32_C(0x7f);
static const uint32_t ALIGNMENT_MASK = UINT32_C(0x3);
static const uint32_t USED_MASK = UINT32_C(0x000fffff);
static bool valid_alignment(unsigned int alignment) {
return alignment == TEXT_ALIGN_LEFT
|| alignment == TEXT_ALIGN_CENTER
|| alignment == TEXT_ALIGN_RIGHT;
}
bool text_style_encode(
const TextStyle *style,
uint32_t *out_code
) {
if (style == NULL || out_code == NULL) {
return false;
}
if (style->size == 0
|| !valid_alignment(style->alignment)) {
return false;
}
uint32_t code = 0;
code |= (uint32_t)style->font_id << FONT_ID_SHIFT;
code |= (uint32_t)style->size << SIZE_SHIFT;
code |= (uint32_t)style->alignment << ALIGNMENT_SHIFT;
code |= (uint32_t)style->bold << BOLD_SHIFT;
code |= (uint32_t)style->italic << ITALIC_SHIFT;
code |= (uint32_t)style->underline << UNDERLINE_SHIFT;
*out_code = code;
return true;
}
bool text_style_decode(
uint32_t code,
TextStyle *out_style
) {
if (out_style == NULL || (code & ~USED_MASK) != 0) {
return false;
}
unsigned int size =
(unsigned int)((code >> SIZE_SHIFT) & SIZE_MASK);
unsigned int alignment =
(unsigned int)(
(code >> ALIGNMENT_SHIFT) & ALIGNMENT_MASK
);
if (size == 0 || !valid_alignment(alignment)) {
return false;
}
TextStyle style = {0};
style.font_id =
(unsigned int)(
(code >> FONT_ID_SHIFT) & FONT_ID_MASK
);
style.size = size;
style.alignment = alignment;
style.bold = (unsigned int)((code >> BOLD_SHIFT) & 1u);
style.italic =
(unsigned int)((code >> ITALIC_SHIFT) & 1u);
style.underline =
(unsigned int)((code >> UNDERLINE_SHIFT) & 1u);
*out_style = style;
return true;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
sizeof(TextStyle) 相等也只能说明某个实现恰好分配了相同数量的字节,不能证明字段位序、填充位或字节序符合交换格式。显式编码才给出了跨实现稳定的数值布局。