blob: 76ae2366e8ddd5f6845aab8190d62503f2448543 [file] [log] [blame]
Thiago Macieiraf1cadf02015-05-08 17:19:17 -07001/****************************************************************************
2**
3** Copyright (C) 2015 Intel Corporation
4**
5** Permission is hereby granted, free of charge, to any person obtaining a copy
6** of this software and associated documentation files (the "Software"), to deal
7** in the Software without restriction, including without limitation the rights
8** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9** copies of the Software, and to permit persons to whom the Software is
10** furnished to do so, subject to the following conditions:
11**
12** The above copyright notice and this permission notice shall be included in
13** all copies or substantial portions of the Software.
14**
15** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21** THE SOFTWARE.
22**
23****************************************************************************/
24
25#define _BSD_SOURCE
26#include "cbor.h"
27#include "cborconstants_p.h"
28#include "compilersupport_p.h"
29
30#include <assert.h>
31#include <endian.h>
32#include <stdlib.h>
33#include <string.h>
34
35void cbor_encoder_init(CborEncoder *encoder, char *buffer, size_t size, int flags)
36{
37 encoder->ptr = buffer;
38 encoder->end = buffer + size;
39 encoder->flags = flags;
40}
41
42static inline void put16(char *where, uint16_t v)
43{
44 v = htobe16(v);
45 memcpy(where, &v, sizeof(v));
46}
47
48static inline void put32(char *where, uint32_t v)
49{
50 v = htobe32(v);
51 memcpy(where, &v, sizeof(v));
52}
53
54static inline void put64(char *where, uint64_t v)
55{
56 v = htobe64(v);
57 memcpy(where, &v, sizeof(v));
58}
59
60static inline CborError append_to_buffer(CborEncoder *encoder, const char *data, size_t len)
61{
62 if (encoder->ptr + len > encoder->end)
63 return CborErrorOutOfMemory;
64 memcpy(encoder->ptr, data, len);
65 encoder->ptr += len;
66 return CborNoError;
67}
68
69static inline CborError encode_number(CborEncoder *encoder, uint64_t ui, uint8_t shiftedMajorType)
70{
71 size_t buflen;
72 char buf[1 + sizeof(uint64_t)];
73 buf[0] = shiftedMajorType;
74
75 if (ui < Value8Bit) {
76 buf[0] += ui;
77 return append_to_buffer(encoder, buf, 1);
78 }
79
80 if (ui <= UINT8_MAX) {
81 buf[0] += Value8Bit;
82 buf[1] = (uint8_t)ui;
83 buflen = 1 + sizeof(uint8_t);
84 } else if (ui <= UINT16_MAX) {
85 buf[0] += Value16Bit;
86 put16(buf + 1, ui);
87 buflen = 1 + sizeof(uint16_t);
88 } else if (ui <= UINT32_MAX) {
89 buf[0] += Value32Bit;
90 put32(buf + 1, ui);
91 buflen = 1 + sizeof(uint32_t);
92 } else {
93 buf[0] += Value64Bit;
94 put64(buf + 1, ui);
95 buflen = 1 + sizeof(uint64_t);
96 }
97
98 assert(buflen <= sizeof(buf));
99 return append_to_buffer(encoder, buf, buflen);
100}
101
102CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value)
103{
104 return encode_number(encoder, value, UnsignedIntegerType << MajorTypeShift);
105}
106
107CborError cbor_encode_int(CborEncoder *encoder, int64_t value)
108{
109 // adapted from code in RFC 7049 appendix C (pseudocode)
110 uint64_t ui = value >> 63; // extend sign to whole length
111 uint8_t majorType = ui & 0x20; // extract major type
112 ui ^= value; // complement negatives
113 return encode_number(encoder, ui, majorType);
114}
115
116CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value)
117{
118#ifndef CBOR_ENCODER_NO_CHECK_USER
119 // check if this is a valid simple type
120 if (value >= HalfPrecisionFloat && value <= Break)
121 return CborErrorIllegalSimpleType;
122#endif
123 return encode_number(encoder, value, SimpleTypesType << MajorTypeShift);
124}
125
126CborError cbor_encode_half_float(CborEncoder *encoder, const void *value)
127{
128 char buf[1 + sizeof(uint16_t)] = { CborHalfFloatType };
129 put16(buf + 1, *(const uint16_t*)value);
130 return append_to_buffer(encoder, buf, sizeof(buf));
131}
132
133CborError cbor_encode_float(CborEncoder *encoder, const float *value)
134{
135 char buf[1 + sizeof(uint32_t)] = { CborFloatType };
136 put32(buf + 1, *(const uint32_t*)value);
137 return append_to_buffer(encoder, buf, sizeof(buf));
138}
139
140CborError cbor_encode_double(CborEncoder *encoder, const double *value)
141{
142 char buf[1 + sizeof(uint64_t)] = { CborDoubleType };
143 put64(buf + 1, *(const uint64_t*)value);
144 return append_to_buffer(encoder, buf, sizeof(buf));
145}
Thiago Macieira8f98a112015-05-08 17:25:29 -0700146
147CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag)
148{
149 return encode_number(encoder, tag, TagType << MajorTypeShift);
150}