1 //
2 // MessagePack for C++ serializing routine
3 //
4 // Copyright (C) 2008-2016 FURUHASHI Sadayuki and KONDO Takatoshi
5 //
6 //    Distributed under the Boost Software License, Version 1.0.
7 //    (See accompanying file LICENSE_1_0.txt or copy at
8 //    http://www.boost.org/LICENSE_1_0.txt)
9 //
10 #ifndef MSGPACK_V1_PACK_HPP
11 #define MSGPACK_V1_PACK_HPP
12 
13 #include "msgpack/v1/pack_decl.hpp"
14 
15 #include <stdexcept>
16 #include <limits>
17 #include <cstring>
18 #include <climits>
19 #include <ostream>
20 
21 namespace msgpack {
22 
23 /// @cond
MSGPACK_API_VERSION_NAMESPACE(v1)24 MSGPACK_API_VERSION_NAMESPACE(v1) {
25 /// @endcond
26 
27 /// The class template that supports continuous packing.
28 /**
29  * @tparam Stream  Any type that have a member function `Stream write(const char*, size_t s)`
30  *
31  */
32 template <typename Stream>
33 class packer {
34 public:
35     /// Constructor
36     /**
37      * This constructor is left for compatibility.
38      * Use `packer(Stream& s)` instead of the constructor.
39      *
40      * @param s A pointer to packing destination stream object.
41      */
42     packer(Stream* s);
43     /// Constructor
44     /**
45      * @param s Packing destination stream object.
46      */
47     packer(Stream& s);
48 
49 public:
50     /// Packing function template
51     /**
52      * @tparam T The type of packing object.
53      *
54      * @param v a packing object.
55      *
56      * @return The reference of `*this`.
57      */
58     template <typename T>
59     packer<Stream>& pack(const T& v);
60 
61     /// Packing uint8
62     /**
63      * The byte size of the packed data depends on `d`.
64      * The packed type is positive fixnum or uint8.
65      * The minimum byte size expression is used.
66      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
67      *
68      * @param d a packing object.
69      *
70      * @return The reference of `*this`.
71      */
72     packer<Stream>& pack_uint8(uint8_t d);
73 
74     /// Packing uint16
75     /**
76      * The byte size of the packed data depends on `d`.
77      * The packed type is positive fixnum, uint8 or uint16.
78      * The minimum byte size expression is used.
79      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
80      *
81      * @param d a packing object.
82      *
83      * @return The reference of `*this`.
84      */
85     packer<Stream>& pack_uint16(uint16_t d);
86 
87     /// Packing uint32
88     /**
89      * The byte size of the packed data depends on `d`.
90      * The packed type is positive fixnum, uint8, uint16 or uint32.
91      * The minimum byte size expression is used.
92      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
93      *
94      * @param d a packing object.
95      *
96      * @return The reference of `*this`.
97      */
98     packer<Stream>& pack_uint32(uint32_t d);
99 
100     /// Packing uint16
101     /**
102      * The byte size of the packed data depends on `d`.
103      * The packed type is positive fixnum, uint8, uint16, uint32 or uint64.
104      * The minimum byte size expression is used.
105      * positive fixnum, uint8, uint16, or uint32 is used.
106      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
107      *
108      * @param d a packing object.
109      *
110      * @return The reference of `*this`.
111      */
112     packer<Stream>& pack_uint64(uint64_t d);
113 
114     /// Packing int8
115     /**
116      * The byte size of the packed data depends on `d`.
117      * If `d` is zero or positive, the packed type is positive fixnum, or uint8,
118      * else the packed type is negative fixnum, or int8
119      * The minimum byte size expression is used.
120      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
121      *
122      * @param d a packing object.
123      *
124      * @return The reference of `*this`.
125      */
126     packer<Stream>& pack_int8(int8_t d);
127 
128     /// Packing int16
129     /**
130      * The byte size of the packed data depends on `d`.
131      * If `d` is zero or positive, the packed type is positive fixnum, uint8, or uint16,
132      * else the packed type is negative fixnum, int8, or int16.
133      * The minimum byte size expression is used.
134      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
135      *
136      * @param d a packing object.
137      *
138      * @return The reference of `*this`.
139      */
140     packer<Stream>& pack_int16(int16_t d);
141 
142     /// Packing int32
143     /**
144      * The byte size of the packed data depends on `d`.
145      * If `d` is zero or positive, the packed type is positive fixnum, uint8, uint16, or uint32,
146      * else the packed type is negative fixnum, int8, int16, or int32.
147      * The minimum byte size expression is used.
148      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
149      *
150      * @param d a packing object.
151      *
152      * @return The reference of `*this`.
153      */
154     packer<Stream>& pack_int32(int32_t d);
155 
156     /// Packing int32
157     /**
158      * The byte size of the packed data depends on `d`.
159      * If `d` is zero or positive, the packed type is positive fixnum, uint8, uint16, uint32, or uint64,
160      * else the packed type is negative fixnum, int8, int16, int32, or int64.
161      * The minimum byte size expression is used.
162      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
163      *
164      * @param d a packing object.
165      *
166      * @return The reference of `*this`.
167      */
168     packer<Stream>& pack_int64(int64_t d);
169 
170 
171 
172     /// Packing uint8 (fixed packed type).
173     /**
174      * The packed type is always uint8.
175      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
176      *
177      * @param d a packing object.
178      *
179      * @return The reference of `*this`.
180      */
181     packer<Stream>& pack_fix_uint8(uint8_t d);
182 
183     /// Packing uint8 (fixed packed type).
184     /**
185      * The packed type is always uint16.
186      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
187      *
188      * @param d a packing object.
189      *
190      * @return The reference of `*this`.
191      */
192     packer<Stream>& pack_fix_uint16(uint16_t d);
193 
194     /// Packing uint8 (fixed packed type).
195     /**
196      * The packed type is always uint32.
197      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
198      *
199      * @param d a packing object.
200      *
201      * @return The reference of `*this`.
202      */
203     packer<Stream>& pack_fix_uint32(uint32_t d);
204 
205     /// Packing uint8 (fixed packed type).
206     /**
207      * The packed type is always uint64.
208      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
209      *
210      * @param d a packing object.
211      *
212      * @return The reference of `*this`.
213      */
214     packer<Stream>& pack_fix_uint64(uint64_t d);
215 
216     /// Packing uint8 (fixed packed type).
217     /**
218      * The packed type is always int8.
219      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
220      *
221      * @param d a packing object.
222      *
223      * @return The reference of `*this`.
224      */
225     packer<Stream>& pack_fix_int8(int8_t d);
226 
227     /// Packing uint8 (fixed packed type).
228     /**
229      * The packed type is always int16.
230      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
231      *
232      * @param d a packing object.
233      *
234      * @return The reference of `*this`.
235      */
236     packer<Stream>& pack_fix_int16(int16_t d);
237 
238     /// Packing uint8 (fixed packed type).
239     /**
240      * The packed type is always int32.
241      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
242      *
243      * @param d a packing object.
244      *
245      * @return The reference of `*this`.
246      */
247     packer<Stream>& pack_fix_int32(int32_t d);
248 
249     /// Packing uint8 (fixed packed type).
250     /**
251      * The packed type is always int64.
252      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
253      *
254      * @param d a packing object.
255      *
256      * @return The reference of `*this`.
257      */
258     packer<Stream>& pack_fix_int64(int64_t d);
259 
260 
261     /// Packing char
262     /**
263      * The byte size of the packed data depends on `d`.
264      * If `d` is zero or positive, the packed type is positive fixnum, or uint*,
265      * else the packed type is negative fixnum, or int*
266      * The minimum byte size expression is used.
267      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
268      *
269      * @param d a packing object.
270      *
271      * @return The reference of `*this`.
272      */
273     packer<Stream>& pack_char(char d);
274 
275     /// Packing wchar_t
276     /**
277      * The byte size of the packed data depends on `d`.
278      * If `d` is zero or positive, the packed type is positive fixnum, or uint*,
279      * else the packed type is negative fixnum, or int*
280      * The minimum byte size expression is used.
281      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
282      *
283      * @param d a packing object.
284      *
285      * @return The reference of `*this`.
286      */
287     packer<Stream>& pack_wchar(wchar_t d);
288 
289     /// Packing signed char
290     /**
291      * The byte size of the packed data depends on `d`.
292      * If `d` is zero or positive, the packed type is positive fixnum, or uint*,
293      * else the packed type is negative fixnum, or int*
294      * The minimum byte size expression is used.
295      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
296      *
297      * @param d a packing object.
298      *
299      * @return The reference of `*this`.
300      */
301     packer<Stream>& pack_signed_char(signed char d);
302 
303     /// Packing short
304     /**
305      * The byte size of the packed data depends on `d`.
306      * If `d` is zero or positive, the packed type is positive fixnum, or uint*,
307      * else the packed type is negative fixnum, or int*
308      * The minimum byte size expression is used.
309      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
310      *
311      * @param d a packing object.
312      *
313      * @return The reference of `*this`.
314      */
315     packer<Stream>& pack_short(short d);
316 
317     /// Packing int
318     /**
319      * The byte size of the packed data depends on `d`.
320      * If `d` is zero or positive, the packed type is positive fixnum, or uint*,
321      * else the packed type is negative fixnum, or int*
322      * The minimum byte size expression is used.
323      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
324      *
325      * @param d a packing object.
326      *
327      * @return The reference of `*this`.
328      */
329     packer<Stream>& pack_int(int d);
330 
331     /// Packing long
332     /**
333      * The byte size of the packed data depends on `d`.
334      * If `d` is zero or positive, the packed type is positive fixnum, or uint*,
335      * else the packed type is negative fixnum, or int*
336      * The minimum byte size expression is used.
337      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
338      *
339      * @param d a packing object.
340      *
341      * @return The reference of `*this`.
342      */
343     packer<Stream>& pack_long(long d);
344 
345     /// Packing long long
346     /**
347      * The byte size of the packed data depends on `d`.
348      * If `d` is zero or positive, the packed type is positive fixnum, or uint*,
349      * else the packed type is negative fixnum, or int*
350      * The minimum byte size expression is used.
351      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
352      *
353      * @param d a packing object.
354      *
355      * @return The reference of `*this`.
356      */
357     packer<Stream>& pack_long_long(long long d);
358 
359 
360     /// Packing unsigned char
361     /**
362      * The byte size of the packed data depends on `d`.
363      * The packed type is positive fixnum, or uint*.
364      * The minimum byte size expression is used.
365      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
366      *
367      * @param d a packing object.
368      *
369      * @return The reference of `*this`.
370      */
371     packer<Stream>& pack_unsigned_char(unsigned char d);
372 
373     /// Packing unsigned short
374     /**
375      * The byte size of the packed data depends on `d`.
376      * The packed type is positive fixnum, or uint*.
377      * The minimum byte size expression is used.
378      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
379      *
380      * @param d a packing object.
381      *
382      * @return The reference of `*this`.
383      */
384     packer<Stream>& pack_unsigned_short(unsigned short d);
385 
386     /// Packing unsigned int
387     /**
388      * The byte size of the packed data depends on `d`.
389      * The packed type is positive fixnum, or uint*.
390      * The minimum byte size expression is used.
391      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
392      *
393      * @param d a packing object.
394      *
395      * @return The reference of `*this`.
396      */
397     packer<Stream>& pack_unsigned_int(unsigned int d);
398 
399     /// Packing unsigned long
400     /**
401      * The byte size of the packed data depends on `d`.
402      * The packed type is positive fixnum, or uint*.
403      * The minimum byte size expression is used.
404      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
405      *
406      * @param d a packing object.
407      *
408      * @return The reference of `*this`.
409      */
410     packer<Stream>& pack_unsigned_long(unsigned long d);
411 
412     /// Packing unsigned long long
413     /**
414      * The byte size of the packed data depends on `d`.
415      * The packed type is positive fixnum, or uint*.
416      * The minimum byte size expression is used.
417      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int
418      *
419      * @param d a packing object.
420      *
421      * @return The reference of `*this`.
422      */
423     packer<Stream>& pack_unsigned_long_long(unsigned long long d);
424 
425     /// Packing float
426     /**
427      * The packed type is float32.
428      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-float
429      *
430      * @param d a packing object.
431      *
432      * @return The reference of `*this`.
433      */
434     packer<Stream>& pack_float(float d);
435 
436     /// Packing double
437     /**
438      * The packed type is float64.
439      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-float
440      *
441      * @param d a packing object.
442      *
443      * @return The reference of `*this`.
444      */
445     packer<Stream>& pack_double(double d);
446 
447 
448     /// Packing nil
449     /**
450      * The packed type is nil.
451      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-nil
452      *
453      * @return The reference of `*this`.
454      */
455     packer<Stream>& pack_nil();
456 
457     /// Packing true
458     /**
459      * The packed type is bool, value is true.
460      * See https://github.com/msgpack/msgpack/blob/master/spec.md#bool-format-family
461      *
462      * @return The reference of `*this`.
463      */
464     packer<Stream>& pack_true();
465 
466     /// Packing false
467     /**
468      * The packed type is bool, value is false.
469      * See https://github.com/msgpack/msgpack/blob/master/spec.md#bool-format-family
470      *
471      * @return The reference of `*this`.
472      */
473     packer<Stream>& pack_false();
474 
475     /// Packing array header and size
476     /**
477      * The packed type is array header and array size.
478      * You need to pack `n` msgpack objects following this header and size.
479      * See https://github.com/msgpack/msgpack/blob/master/spec.md#array-format-family
480      *
481      * @param n The number of array elements (array size).
482      *
483      * @return The reference of `*this`.
484      */
485     packer<Stream>& pack_array(uint32_t n);
486 
487     /// Packing map header and size
488     /**
489      * The packed type is map header and map size.
490      * You need to pack `n` pairs of msgpack objects following this header and size.
491      * See https://github.com/msgpack/msgpack/blob/master/spec.md#map-format-family
492      *
493      * @param n The number of array elements (array size).
494      *
495      * @return The reference of `*this`.
496      */
497     packer<Stream>& pack_map(uint32_t n);
498 
499 
500     /// Packing str header and length
501     /**
502      * The packed type is str header and length.
503      * The minimum byte size length expression is used.
504      * You need to call `pack_str_body(const char* b, uint32_t l)` after this function calling with the same `l` value.
505      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-str
506      *
507      * @param l The length of string.
508      *
509      * @return The reference of `*this`.
510      */
511     packer<Stream>& pack_str(uint32_t l);
512 
513     /// Packing str body
514     /**
515      * You need to call this function just after `pack_str(uint32_t l)` calling.
516      * The value `l` should be the same as `pack_str(uint32_t l)` argument `l`.
517      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-str
518      *
519      * @param l The length of string.
520      *
521      * @return The reference of `*this`.
522      */
523     packer<Stream>& pack_str_body(const char* b, uint32_t l);
524 
525     /// Packing raw (v4) header and length
526     /**
527      * The packed type is raw header and length.
528      * The minimum byte size length expression is used.
529      * The format raw (v4) is old MessagePack version4 format.
530      * You need to call `pack_v4raw_body(const char* b, uint32_t l)` after this function calling with the same `l` value.
531      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-str
532      *
533      * @param l The length of string.
534      *
535      * @return The reference of `*this`.
536      */
537     packer<Stream>& pack_v4raw(uint32_t l);
538 
539     /// Packing raw (v4) body
540     /**
541      * The format raw (v4) is old MessagePack version4 format.
542      * You need to call this function just after `pack_v4raw(uint32_t l)` calling.
543      * The value `l` should be the same as `pack_v4raw(uint32_t l)` argument `l`.
544      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-str
545      *
546      * @param l The length of string.
547      *
548      * @return The reference of `*this`.
549      */
550     packer<Stream>& pack_v4raw_body(const char* b, uint32_t l);
551 
552     /// Packing bin header and length
553     /**
554      * The packed type is bin header and length.
555      * The minimum byte size length expression is used.
556      * You need to call `pack_bin_body(const char* b, uint32_t l)` after this function calling with the same `l` value.
557      * See https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family
558      *
559      * @param l The length of string.
560      *
561      * @return The reference of `*this`.
562      */
563     packer<Stream>& pack_bin(uint32_t l);
564 
565     /// Packing bin body
566     /**
567      * You need to call this function just after `pack_bin(uint32_t l)` calling.
568      * The value `l` should be the same as `pack_bin(uint32_t l)` argument `l`.
569      * See https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family
570      *
571      * @param l The length of string.
572      *
573      * @return The reference of `*this`.
574      */
575     packer<Stream>& pack_bin_body(const char* b, uint32_t l);
576 
577     /// Packing ext header, type, and length
578     /**
579      * The packed type is ext.
580      * The minimum byte size length expression is used.
581      * The length 1, 2, 4, 8, and 16 can be encoded in the header.
582      * You need to call `pack_ext_body(const char* b, uint32_t l)` after this function calling with the same `l` value.
583      * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-ext
584      *
585      * @param l The length of string.
586      *
587      * @return The reference of `*this`.
588      */
589     packer<Stream>& pack_ext(size_t l, int8_t type);
590 
591     /// Packing ext body
592     /**
593      * You need to call this function just after `pack_ext(size_t l, int8_t type)` calling.
594      * The value `l` should be the same as `pack_ext(size_t l, int8_t type)` argument `l`.
595      * See https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family
596      *
597      * @param l The length of string.
598      *
599      * @return The reference of `*this`.
600      */
601     packer<Stream>& pack_ext_body(const char* b, uint32_t l);
602 
603 private:
604     template <typename T>
605     void pack_imp_uint8(T d);
606     template <typename T>
607     void pack_imp_uint16(T d);
608     template <typename T>
609     void pack_imp_uint32(T d);
610     template <typename T>
611     void pack_imp_uint64(T d);
612     template <typename T>
613     void pack_imp_int8(T d);
614     template <typename T>
615     void pack_imp_int16(T d);
616     template <typename T>
617     void pack_imp_int32(T d);
618     template <typename T>
619     void pack_imp_int64(T d);
620 
621     void append_buffer(const char* buf, size_t len)
622     {
623         append_buffer(&Stream::write, buf, len);
624     }
625 
626     template <typename Ret, typename Cls, typename SizeType>
627     void append_buffer(Ret (Cls::*)(const char*, SizeType), const char* buf, size_t len)
628     {
629         m_stream.write(buf, static_cast<SizeType>(len));
630     }
631 
632 private:
633     Stream& m_stream;
634 
635 #if defined(MSGPACK_USE_CPP03)
636 private:
637     packer(const packer&);
638     packer& operator=(const packer&);
639     packer();
640 #else  // defined(MSGPACK_USE_CPP03)
641 public:
642     packer(const packer&) = delete;
643     packer& operator=(const packer&) = delete;
644     packer() = delete;
645 #endif // defined(MSGPACK_USE_CPP03)
646 };
647 
648 
649 /// Pack the value as MessagePack format into the stream
650 /**
651  * This function template is left for compatibility.
652  * Use `void pack(Stream& s, const T& v)` instead of the function template.
653  *
654  * @tparam Stream Any type that have a member function `Stream write(const char*, size_t s)`
655  * @tparam T Any type that is adapted to MessagePack
656  * @param s The pointer to packing destination stream
657  * @param v Packing value
658  */
659 template <typename Stream, typename T>
660 inline void pack(Stream* s, const T& v)
661 {
662     packer<Stream>(*s).pack(v);
663 }
664 
665 /// Pack the value as MessagePack format into the stream
666 /**
667  * @tparam Stream Any type that have a member function `Stream write(const char*, size_t s)`
668  * @tparam T Any type that is adapted to MessagePack
669  * @param s Packing destination stream
670  * @param v Packing value
671  */
672 template <typename Stream, typename T>
673 inline void pack(Stream& s, const T& v)
674 {
675     packer<Stream>(s).pack(v);
676 }
677 
678 
679 #if MSGPACK_ENDIAN_LITTLE_BYTE
680 template <typename T>
681 inline char take8_8(T d) {
682     return static_cast<char>(reinterpret_cast<uint8_t*>(&d)[0]);
683 }
684 template <typename T>
685 inline char take8_16(T d) {
686     return static_cast<char>(reinterpret_cast<uint8_t*>(&d)[0]);
687 }
688 template <typename T>
689 inline char take8_32(T d) {
690     return static_cast<char>(reinterpret_cast<uint8_t*>(&d)[0]);
691 }
692 template <typename T>
693 inline char take8_64(T d) {
694     return static_cast<char>(reinterpret_cast<uint8_t*>(&d)[0]);
695 }
696 
697 #elif MSGPACK_ENDIAN_BIG_BYTE
698 
699 template <typename T>
700 inline char take8_8(T d) {
701     return static_cast<char>(reinterpret_cast<uint8_t*>(&d)[0]);
702 }
703 template <typename T>
704 inline char take8_16(T d) {
705     return static_cast<char>(reinterpret_cast<uint8_t*>(&d)[1]);
706 }
707 template <typename T>
708 inline char take8_32(T d) {
709     return static_cast<char>(reinterpret_cast<uint8_t*>(&d)[3]);
710 }
711 template <typename T>
712 inline char take8_64(T d) {
713     return static_cast<char>(reinterpret_cast<uint8_t*>(&d)[7]);
714 }
715 
716 #else
717 #error msgpack-c supports only big endian and little endian
718 #endif
719 
720 template <typename Stream>
721 inline packer<Stream>::packer(Stream* s) : m_stream(*s) { }
722 
723 template <typename Stream>
724 inline packer<Stream>::packer(Stream& s) : m_stream(s) { }
725 
726 
727 template <typename Stream>
728 inline packer<Stream>& packer<Stream>::pack_uint8(uint8_t d)
729 { pack_imp_uint8(d); return *this; }
730 
731 template <typename Stream>
732 inline packer<Stream>& packer<Stream>::pack_uint16(uint16_t d)
733 { pack_imp_uint16(d); return *this; }
734 
735 template <typename Stream>
736 inline packer<Stream>& packer<Stream>::pack_uint32(uint32_t d)
737 { pack_imp_uint32(d); return *this; }
738 
739 template <typename Stream>
740 inline packer<Stream>& packer<Stream>::pack_uint64(uint64_t d)
741 { pack_imp_uint64(d); return *this; }
742 
743 template <typename Stream>
744 inline packer<Stream>& packer<Stream>::pack_int8(int8_t d)
745 { pack_imp_int8(d); return *this; }
746 
747 template <typename Stream>
748 inline packer<Stream>& packer<Stream>::pack_int16(int16_t d)
749 { pack_imp_int16(d); return *this; }
750 
751 template <typename Stream>
752 inline packer<Stream>& packer<Stream>::pack_int32(int32_t d)
753 { pack_imp_int32(d); return *this; }
754 
755 template <typename Stream>
756 inline packer<Stream>& packer<Stream>::pack_int64(int64_t d)
757 { pack_imp_int64(d); return *this;}
758 
759 
760 template <typename Stream>
761 inline packer<Stream>& packer<Stream>::pack_fix_uint8(uint8_t d)
762 {
763     char buf[2] = {static_cast<char>(0xccu), take8_8(d)};
764     append_buffer(buf, 2);
765     return *this;
766 }
767 
768 template <typename Stream>
769 inline packer<Stream>& packer<Stream>::pack_fix_uint16(uint16_t d)
770 {
771     char buf[3];
772     buf[0] = static_cast<char>(0xcdu); _msgpack_store16(&buf[1], d);
773     append_buffer(buf, 3);
774     return *this;
775 }
776 
777 template <typename Stream>
778 inline packer<Stream>& packer<Stream>::pack_fix_uint32(uint32_t d)
779 {
780     char buf[5];
781     buf[0] = static_cast<char>(0xceu); _msgpack_store32(&buf[1], d);
782     append_buffer(buf, 5);
783     return *this;
784 }
785 
786 template <typename Stream>
787 inline packer<Stream>& packer<Stream>::pack_fix_uint64(uint64_t d)
788 {
789     char buf[9];
790     buf[0] = static_cast<char>(0xcfu); _msgpack_store64(&buf[1], d);
791     append_buffer(buf, 9);
792     return *this;
793 }
794 
795 template <typename Stream>
796 inline packer<Stream>& packer<Stream>::pack_fix_int8(int8_t d)
797 {
798     char buf[2] = {static_cast<char>(0xd0u), take8_8(d)};
799     append_buffer(buf, 2);
800     return *this;
801 }
802 
803 template <typename Stream>
804 inline packer<Stream>& packer<Stream>::pack_fix_int16(int16_t d)
805 {
806     char buf[3];
807     buf[0] = static_cast<char>(0xd1u); _msgpack_store16(&buf[1], (uint16_t)d);
808     append_buffer(buf, 3);
809     return *this;
810 }
811 
812 template <typename Stream>
813 inline packer<Stream>& packer<Stream>::pack_fix_int32(int32_t d)
814 {
815     char buf[5];
816     buf[0] = static_cast<char>(0xd2u); _msgpack_store32(&buf[1], (uint32_t)d);
817     append_buffer(buf, 5);
818     return *this;
819 }
820 
821 template <typename Stream>
822 inline packer<Stream>& packer<Stream>::pack_fix_int64(int64_t d)
823 {
824     char buf[9];
825     buf[0] = static_cast<char>(0xd3u); _msgpack_store64(&buf[1], d);
826     append_buffer(buf, 9);
827     return *this;
828 }
829 
830 
831 template <typename Stream>
832 inline packer<Stream>& packer<Stream>::pack_char(char d)
833 {
834 #if defined(CHAR_MIN)
835 #if CHAR_MIN < 0
836     pack_imp_int8(d);
837 #else
838     pack_imp_uint8(d);
839 #endif
840 #else
841 #error CHAR_MIN is not defined
842 #endif
843     return *this;
844 }
845 
846 template <typename Stream>
847 inline packer<Stream>& packer<Stream>::pack_wchar(wchar_t d)
848 {
849     if (d < 0) {
850         pack_imp_int64(static_cast<int64_t>(d));
851     }
852     else {
853         pack_imp_uint64(static_cast<uint64_t>(d));
854     }
855     return *this;
856 }
857 
858 template <typename Stream>
859 inline packer<Stream>& packer<Stream>::pack_signed_char(signed char d)
860 {
861     pack_imp_int8(d);
862     return *this;
863 }
864 
865 template <typename Stream>
866 inline packer<Stream>& packer<Stream>::pack_short(short d)
867 {
868 #if defined(SIZEOF_SHORT)
869 #if SIZEOF_SHORT == 2
870     pack_imp_int16(d);
871 #elif SIZEOF_SHORT == 4
872     pack_imp_int32(d);
873 #else
874     pack_imp_int64(d);
875 #endif
876 
877 #elif defined(SHRT_MAX)
878 #if SHRT_MAX == 0x7fff
879     pack_imp_int16(d);
880 #elif SHRT_MAX == 0x7fffffff
881     pack_imp_int32(d);
882 #else
883     pack_imp_int64(d);
884 #endif
885 
886 #else
887     if(sizeof(short) == 2) {
888         pack_imp_int16(d);
889     } else if(sizeof(short) == 4) {
890         pack_imp_int32(d);
891     } else {
892         pack_imp_int64(d);
893     }
894 #endif
895     return *this;
896 }
897 
898 template <typename Stream>
899 inline packer<Stream>& packer<Stream>::pack_int(int d)
900 {
901 #if defined(SIZEOF_INT)
902 #if SIZEOF_INT == 2
903     pack_imp_int16(d);
904 #elif SIZEOF_INT == 4
905     pack_imp_int32(d);
906 #else
907     pack_imp_int64(d);
908 #endif
909 
910 #elif defined(INT_MAX)
911 #if INT_MAX == 0x7fff
912     pack_imp_int16(d);
913 #elif INT_MAX == 0x7fffffff
914     pack_imp_int32(d);
915 #else
916     pack_imp_int64(d);
917 #endif
918 
919 #else
920     if(sizeof(int) == 2) {
921         pack_imp_int16(d);
922     } else if(sizeof(int) == 4) {
923         pack_imp_int32(d);
924     } else {
925         pack_imp_int64(d);
926     }
927 #endif
928     return *this;
929 }
930 
931 template <typename Stream>
932 inline packer<Stream>& packer<Stream>::pack_long(long d)
933 {
934 #if defined(SIZEOF_LONG)
935 #if SIZEOF_LONG == 2
936     pack_imp_int16(d);
937 #elif SIZEOF_LONG == 4
938     pack_imp_int32(d);
939 #else
940     pack_imp_int64(d);
941 #endif
942 
943 #elif defined(LONG_MAX)
944 #if LONG_MAX == 0x7fffL
945     pack_imp_int16(d);
946 #elif LONG_MAX == 0x7fffffffL
947     pack_imp_int32(d);
948 #else
949     pack_imp_int64(d);
950 #endif
951 
952 #else
953     if(sizeof(long) == 2) {
954         pack_imp_int16(d);
955     } else if(sizeof(long) == 4) {
956         pack_imp_int32(d);
957     } else {
958         pack_imp_int64(d);
959     }
960 #endif
961     return *this;
962 }
963 
964 template <typename Stream>
965 inline packer<Stream>& packer<Stream>::pack_long_long(long long d)
966 {
967 #if defined(SIZEOF_LONG_LONG)
968 #if SIZEOF_LONG_LONG == 2
969     pack_imp_int16(d);
970 #elif SIZEOF_LONG_LONG == 4
971     pack_imp_int32(d);
972 #else
973     pack_imp_int64(d);
974 #endif
975 
976 #elif defined(LLONG_MAX)
977 #if LLONG_MAX == 0x7fffL
978     pack_imp_int16(d);
979 #elif LLONG_MAX == 0x7fffffffL
980     pack_imp_int32(d);
981 #else
982     pack_imp_int64(d);
983 #endif
984 
985 #else
986     if(sizeof(long long) == 2) {
987         pack_imp_int16(d);
988     } else if(sizeof(long long) == 4) {
989         pack_imp_int32(d);
990     } else {
991         pack_imp_int64(d);
992     }
993 #endif
994     return *this;
995 }
996 
997 
998 template <typename Stream>
999 inline packer<Stream>& packer<Stream>::pack_unsigned_char(unsigned char d)
1000 {
1001     pack_imp_uint8(d);
1002     return *this;
1003 }
1004 
1005 template <typename Stream>
1006 inline packer<Stream>& packer<Stream>::pack_unsigned_short(unsigned short d)
1007 {
1008 #if defined(SIZEOF_SHORT)
1009 #if SIZEOF_SHORT == 2
1010     pack_imp_uint16(d);
1011 #elif SIZEOF_SHORT == 4
1012     pack_imp_uint32(d);
1013 #else
1014     pack_imp_uint64(d);
1015 #endif
1016 
1017 #elif defined(USHRT_MAX)
1018 #if USHRT_MAX == 0xffffU
1019     pack_imp_uint16(d);
1020 #elif USHRT_MAX == 0xffffffffU
1021     pack_imp_uint32(d);
1022 #else
1023     pack_imp_uint64(d);
1024 #endif
1025 
1026 #else
1027     if(sizeof(unsigned short) == 2) {
1028         pack_imp_uint16(d);
1029     } else if(sizeof(unsigned short) == 4) {
1030         pack_imp_uint32(d);
1031     } else {
1032         pack_imp_uint64(d);
1033     }
1034 #endif
1035     return *this;
1036 }
1037 
1038 template <typename Stream>
1039 inline packer<Stream>& packer<Stream>::pack_unsigned_int(unsigned int d)
1040 {
1041 #if defined(SIZEOF_INT)
1042 #if SIZEOF_INT == 2
1043     pack_imp_uint16(d);
1044 #elif SIZEOF_INT == 4
1045     pack_imp_uint32(d);
1046 #else
1047     pack_imp_uint64(d);
1048 #endif
1049 
1050 #elif defined(UINT_MAX)
1051 #if UINT_MAX == 0xffffU
1052     pack_imp_uint16(d);
1053 #elif UINT_MAX == 0xffffffffU
1054     pack_imp_uint32(d);
1055 #else
1056     pack_imp_uint64(d);
1057 #endif
1058 
1059 #else
1060     if(sizeof(unsigned int) == 2) {
1061         pack_imp_uint16(d);
1062     } else if(sizeof(unsigned int) == 4) {
1063         pack_imp_uint32(d);
1064     } else {
1065         pack_imp_uint64(d);
1066     }
1067 #endif
1068     return *this;
1069 }
1070 
1071 template <typename Stream>
1072 inline packer<Stream>& packer<Stream>::pack_unsigned_long(unsigned long d)
1073 {
1074 #if defined(SIZEOF_LONG)
1075 #if SIZEOF_LONG == 2
1076     pack_imp_uint16(d);
1077 #elif SIZEOF_LONG == 4
1078     pack_imp_uint32(d);
1079 #else
1080     pack_imp_uint64(d);
1081 #endif
1082 
1083 #elif defined(ULONG_MAX)
1084 #if ULONG_MAX == 0xffffUL
1085     pack_imp_uint16(d);
1086 #elif ULONG_MAX == 0xffffffffUL
1087     pack_imp_uint32(d);
1088 #else
1089     pack_imp_uint64(d);
1090 #endif
1091 
1092 #else
1093     if(sizeof(unsigned long) == 2) {
1094         pack_imp_uint16(d);
1095     } else if(sizeof(unsigned long) == 4) {
1096         pack_imp_uint32(d);
1097     } else {
1098         pack_imp_uint64(d);
1099     }
1100 #endif
1101     return *this;
1102 }
1103 
1104 template <typename Stream>
1105 inline packer<Stream>& packer<Stream>::pack_unsigned_long_long(unsigned long long d)
1106 {
1107 #if defined(SIZEOF_LONG_LONG)
1108 #if SIZEOF_LONG_LONG == 2
1109     pack_imp_uint16(d);
1110 #elif SIZEOF_LONG_LONG == 4
1111     pack_imp_uint32(d);
1112 #else
1113     pack_imp_uint64(d);
1114 #endif
1115 
1116 #elif defined(ULLONG_MAX)
1117 #if ULLONG_MAX == 0xffffUL
1118     pack_imp_uint16(d);
1119 #elif ULLONG_MAX == 0xffffffffUL
1120     pack_imp_uint32(d);
1121 #else
1122     pack_imp_uint64(d);
1123 #endif
1124 
1125 #else
1126     if(sizeof(unsigned long long) == 2) {
1127         pack_imp_uint16(d);
1128     } else if(sizeof(unsigned long long) == 4) {
1129         pack_imp_uint32(d);
1130     } else {
1131         pack_imp_uint64(d);
1132     }
1133 #endif
1134     return *this;
1135 }
1136 
1137 
1138 template <typename Stream>
1139 inline packer<Stream>& packer<Stream>::pack_float(float d)
1140 {
1141     union { float f; uint32_t i; } mem;
1142     mem.f = d;
1143     char buf[5];
1144     buf[0] = static_cast<char>(0xcau); _msgpack_store32(&buf[1], mem.i);
1145     append_buffer(buf, 5);
1146     return *this;
1147 }
1148 
1149 template <typename Stream>
1150 inline packer<Stream>& packer<Stream>::pack_double(double d)
1151 {
1152     union { double f; uint64_t i; } mem;
1153     mem.f = d;
1154     char buf[9];
1155     buf[0] = static_cast<char>(0xcbu);
1156 
1157 #if defined(TARGET_OS_IPHONE)
1158     // ok
1159 #elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi
1160     // https://github.com/msgpack/msgpack-perl/pull/1
1161     mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
1162 #endif
1163     _msgpack_store64(&buf[1], mem.i);
1164     append_buffer(buf, 9);
1165     return *this;
1166 }
1167 
1168 
1169 template <typename Stream>
1170 inline packer<Stream>& packer<Stream>::pack_nil()
1171 {
1172     const char d = static_cast<char>(0xc0u);
1173     append_buffer(&d, 1);
1174     return *this;
1175 }
1176 
1177 template <typename Stream>
1178 inline packer<Stream>& packer<Stream>::pack_true()
1179 {
1180     const char d = static_cast<char>(0xc3u);
1181     append_buffer(&d, 1);
1182     return *this;
1183 }
1184 
1185 template <typename Stream>
1186 inline packer<Stream>& packer<Stream>::pack_false()
1187 {
1188     const char d = static_cast<char>(0xc2u);
1189     append_buffer(&d, 1);
1190     return *this;
1191 }
1192 
1193 
1194 template <typename Stream>
1195 inline packer<Stream>& packer<Stream>::pack_array(uint32_t n)
1196 {
1197     if(n < 16) {
1198         char d = static_cast<char>(0x90u | n);
1199         append_buffer(&d, 1);
1200     } else if(n < 65536) {
1201         char buf[3];
1202         buf[0] = static_cast<char>(0xdcu); _msgpack_store16(&buf[1], static_cast<uint16_t>(n));
1203         append_buffer(buf, 3);
1204     } else {
1205         char buf[5];
1206         buf[0] = static_cast<char>(0xddu); _msgpack_store32(&buf[1], static_cast<uint32_t>(n));
1207         append_buffer(buf, 5);
1208     }
1209     return *this;
1210 }
1211 
1212 template <typename Stream>
1213 inline packer<Stream>& packer<Stream>::pack_map(uint32_t n)
1214 {
1215     if(n < 16) {
1216         unsigned char d = static_cast<unsigned char>(0x80u | n);
1217         char buf = take8_8(d);
1218         append_buffer(&buf, 1);
1219     } else if(n < 65536) {
1220         char buf[3];
1221         buf[0] = static_cast<char>(0xdeu); _msgpack_store16(&buf[1], static_cast<uint16_t>(n));
1222         append_buffer(buf, 3);
1223     } else {
1224         char buf[5];
1225         buf[0] = static_cast<char>(0xdfu); _msgpack_store32(&buf[1], static_cast<uint32_t>(n));
1226         append_buffer(buf, 5);
1227     }
1228     return *this;
1229 }
1230 
1231 template <typename Stream>
1232 inline packer<Stream>& packer<Stream>::pack_str(uint32_t l)
1233 {
1234     if(l < 32) {
1235         unsigned char d = static_cast<uint8_t>(0xa0u | l);
1236         char buf = take8_8(d);
1237         append_buffer(&buf, 1);
1238     } else if(l < 256) {
1239         char buf[2];
1240         buf[0] = static_cast<char>(0xd9u); buf[1] = static_cast<char>(l);
1241         append_buffer(buf, 2);
1242     } else if(l < 65536) {
1243         char buf[3];
1244         buf[0] = static_cast<char>(0xdau); _msgpack_store16(&buf[1], static_cast<uint16_t>(l));
1245         append_buffer(buf, 3);
1246     } else {
1247         char buf[5];
1248         buf[0] = static_cast<char>(0xdbu); _msgpack_store32(&buf[1], static_cast<uint32_t>(l));
1249         append_buffer(buf, 5);
1250     }
1251     return *this;
1252 }
1253 
1254 template <typename Stream>
1255 inline packer<Stream>& packer<Stream>::pack_str_body(const char* b, uint32_t l)
1256 {
1257     append_buffer(b, l);
1258     return *this;
1259 }
1260 
1261 // Raw (V4)
1262 
1263 template <typename Stream>
1264 inline packer<Stream>& packer<Stream>::pack_v4raw(uint32_t l)
1265 {
1266     if(l < 32) {
1267         unsigned char d = static_cast<uint8_t>(0xa0u | l);
1268         char buf = take8_8(d);
1269         append_buffer(&buf, 1);
1270     } else if(l < 65536) {
1271         char buf[3];
1272         buf[0] = static_cast<char>(0xdau); _msgpack_store16(&buf[1], static_cast<uint16_t>(l));
1273         append_buffer(buf, 3);
1274     } else {
1275         char buf[5];
1276         buf[0] = static_cast<char>(0xdbu); _msgpack_store32(&buf[1], static_cast<uint32_t>(l));
1277         append_buffer(buf, 5);
1278     }
1279     return *this;
1280 }
1281 
1282 template <typename Stream>
1283 inline packer<Stream>& packer<Stream>::pack_v4raw_body(const char* b, uint32_t l)
1284 {
1285     append_buffer(b, l);
1286     return *this;
1287 }
1288 
1289 template <typename Stream>
1290 inline packer<Stream>& packer<Stream>::pack_bin(uint32_t l)
1291 {
1292     if(l < 256) {
1293         char buf[2];
1294         buf[0] = static_cast<char>(0xc4u); buf[1] = static_cast<char>(l);
1295         append_buffer(buf, 2);
1296     } else if(l < 65536) {
1297         char buf[3];
1298         buf[0] = static_cast<char>(0xc5u); _msgpack_store16(&buf[1], static_cast<uint16_t>(l));
1299         append_buffer(buf, 3);
1300     } else {
1301         char buf[5];
1302         buf[0] = static_cast<char>(0xc6u); _msgpack_store32(&buf[1], static_cast<uint32_t>(l));
1303         append_buffer(buf, 5);
1304     }
1305     return *this;
1306 }
1307 
1308 template <typename Stream>
1309 inline packer<Stream>& packer<Stream>::pack_bin_body(const char* b, uint32_t l)
1310 {
1311     append_buffer(b, l);
1312     return *this;
1313 }
1314 
1315 template <typename Stream>
1316 inline packer<Stream>& packer<Stream>::pack_ext(size_t l, int8_t type)
1317 {
1318     switch(l) {
1319     case 1: {
1320         char buf[2];
1321         buf[0] = static_cast<char>(0xd4u);
1322         buf[1] = static_cast<char>(type);
1323         append_buffer(buf, 2);
1324     } break;
1325     case 2: {
1326         char buf[2];
1327         buf[0] = static_cast<char>(0xd5u);
1328         buf[1] = static_cast<char>(type);
1329         append_buffer(buf, 2);
1330     } break;
1331     case 4: {
1332         char buf[2];
1333         buf[0] = static_cast<char>(0xd6u);
1334         buf[1] = static_cast<char>(type);
1335         append_buffer(buf, 2);
1336     } break;
1337     case 8: {
1338         char buf[2];
1339         buf[0] = static_cast<char>(0xd7u);
1340         buf[1] = static_cast<char>(type);
1341         append_buffer(buf, 2);
1342     } break;
1343     case 16: {
1344         char buf[2];
1345         buf[0] = static_cast<char>(0xd8u);
1346         buf[1] = static_cast<char>(type);
1347         append_buffer(buf, 2);
1348     } break;
1349     default:
1350         if(l < 256) {
1351             char buf[3];
1352             buf[0] = static_cast<char>(0xc7u);
1353             buf[1] = static_cast<char>(l);
1354             buf[2] = static_cast<char>(type);
1355             append_buffer(buf, 3);
1356         } else if(l < 65536) {
1357             char buf[4];
1358             buf[0] = static_cast<char>(0xc8u);
1359             _msgpack_store16(&buf[1], static_cast<uint16_t>(l));
1360             buf[3] = static_cast<char>(type);
1361             append_buffer(buf, 4);
1362         } else {
1363             char buf[6];
1364             buf[0] = static_cast<char>(0xc9u);
1365             _msgpack_store32(&buf[1], static_cast<uint32_t>(l));
1366             buf[5] = static_cast<char>(type);
1367             append_buffer(buf, 6);
1368         }
1369         break;
1370     }
1371     return *this;
1372 }
1373 
1374 template <typename Stream>
1375 inline packer<Stream>& packer<Stream>::pack_ext_body(const char* b, uint32_t l)
1376 {
1377     append_buffer(b, l);
1378     return *this;
1379 }
1380 
1381 template <typename Stream>
1382 template <typename T>
1383 inline void packer<Stream>::pack_imp_uint8(T d)
1384 {
1385     if(d < (1<<7)) {
1386         /* fixnum */
1387         char buf = take8_8(d);
1388         append_buffer(&buf, 1);
1389     } else {
1390         /* unsigned 8 */
1391         char buf[2] = {static_cast<char>(0xccu), take8_8(d)};
1392         append_buffer(buf, 2);
1393     }
1394 }
1395 
1396 template <typename Stream>
1397 template <typename T>
1398 inline void packer<Stream>::pack_imp_uint16(T d)
1399 {
1400     if(d < (1<<7)) {
1401         /* fixnum */
1402         char buf = take8_16(d);
1403         append_buffer(&buf, 1);
1404     } else if(d < (1<<8)) {
1405         /* unsigned 8 */
1406         char buf[2] = {static_cast<char>(0xccu), take8_16(d)};
1407         append_buffer(buf, 2);
1408     } else {
1409         /* unsigned 16 */
1410         char buf[3];
1411         buf[0] = static_cast<char>(0xcdu); _msgpack_store16(&buf[1], static_cast<uint16_t>(d));
1412         append_buffer(buf, 3);
1413     }
1414 }
1415 
1416 template <typename Stream>
1417 template <typename T>
1418 inline void packer<Stream>::pack_imp_uint32(T d)
1419 {
1420     if(d < (1<<8)) {
1421         if(d < (1<<7)) {
1422             /* fixnum */
1423             char buf = take8_32(d);
1424             append_buffer(&buf, 1);
1425         } else {
1426             /* unsigned 8 */
1427             char buf[2] = {static_cast<char>(0xccu), take8_32(d)};
1428             append_buffer(buf, 2);
1429         }
1430     } else {
1431         if(d < (1<<16)) {
1432             /* unsigned 16 */
1433             char buf[3];
1434             buf[0] = static_cast<char>(0xcdu); _msgpack_store16(&buf[1], static_cast<uint16_t>(d));
1435             append_buffer(buf, 3);
1436         } else {
1437             /* unsigned 32 */
1438             char buf[5];
1439             buf[0] = static_cast<char>(0xceu); _msgpack_store32(&buf[1], static_cast<uint32_t>(d));
1440             append_buffer(buf, 5);
1441         }
1442     }
1443 }
1444 
1445 template <typename Stream>
1446 template <typename T>
1447 inline void packer<Stream>::pack_imp_uint64(T d)
1448 {
1449     if(d < (1ULL<<8)) {
1450         if(d < (1ULL<<7)) {
1451             /* fixnum */
1452             char buf = take8_64(d);
1453             append_buffer(&buf, 1);
1454         } else {
1455             /* unsigned 8 */
1456             char buf[2] = {static_cast<char>(0xccu), take8_64(d)};
1457             append_buffer(buf, 2);
1458         }
1459     } else {
1460         if(d < (1ULL<<16)) {
1461             /* unsigned 16 */
1462             char buf[3];
1463             buf[0] = static_cast<char>(0xcdu); _msgpack_store16(&buf[1], static_cast<uint16_t>(d));
1464             append_buffer(buf, 3);
1465         } else if(d < (1ULL<<32)) {
1466             /* unsigned 32 */
1467             char buf[5];
1468             buf[0] = static_cast<char>(0xceu); _msgpack_store32(&buf[1], static_cast<uint32_t>(d));
1469             append_buffer(buf, 5);
1470         } else {
1471             /* unsigned 64 */
1472             char buf[9];
1473             buf[0] = static_cast<char>(0xcfu); _msgpack_store64(&buf[1], d);
1474             append_buffer(buf, 9);
1475         }
1476     }
1477 }
1478 
1479 template <typename Stream>
1480 template <typename T>
1481 inline void packer<Stream>::pack_imp_int8(T d)
1482 {
1483     if(d < -(1<<5)) {
1484         /* signed 8 */
1485         char buf[2] = {static_cast<char>(0xd0u), take8_8(d)};
1486         append_buffer(buf, 2);
1487     } else {
1488         /* fixnum */
1489         char buf = take8_8(d);
1490         append_buffer(&buf, 1);
1491     }
1492 }
1493 
1494 template <typename Stream>
1495 template <typename T>
1496 inline void packer<Stream>::pack_imp_int16(T d)
1497 {
1498     if(d < -(1<<5)) {
1499         if(d < -(1<<7)) {
1500             /* signed 16 */
1501             char buf[3];
1502             buf[0] = static_cast<char>(0xd1u); _msgpack_store16(&buf[1], static_cast<int16_t>(d));
1503             append_buffer(buf, 3);
1504         } else {
1505             /* signed 8 */
1506             char buf[2] = {static_cast<char>(0xd0u), take8_16(d)};
1507             append_buffer(buf, 2);
1508         }
1509     } else if(d < (1<<7)) {
1510         /* fixnum */
1511         char buf = take8_16(d);
1512         append_buffer(&buf, 1);
1513     } else {
1514         if(d < (1<<8)) {
1515             /* unsigned 8 */
1516             char buf[2] = {static_cast<char>(0xccu), take8_16(d)};
1517             append_buffer(buf, 2);
1518         } else {
1519             /* unsigned 16 */
1520             char buf[3];
1521             buf[0] = static_cast<char>(0xcdu); _msgpack_store16(&buf[1], static_cast<uint16_t>(d));
1522             append_buffer(buf, 3);
1523         }
1524     }
1525 }
1526 
1527 template <typename Stream>
1528 template <typename T>
1529 inline void packer<Stream>::pack_imp_int32(T d)
1530 {
1531     if(d < -(1<<5)) {
1532         if(d < -(1<<15)) {
1533             /* signed 32 */
1534             char buf[5];
1535             buf[0] = static_cast<char>(0xd2u); _msgpack_store32(&buf[1], static_cast<int32_t>(d));
1536             append_buffer(buf, 5);
1537         } else if(d < -(1<<7)) {
1538             /* signed 16 */
1539             char buf[3];
1540             buf[0] = static_cast<char>(0xd1u); _msgpack_store16(&buf[1], static_cast<int16_t>(d));
1541             append_buffer(buf, 3);
1542         } else {
1543             /* signed 8 */
1544             char buf[2] = { static_cast<char>(0xd0u), take8_32(d)};
1545             append_buffer(buf, 2);
1546         }
1547     } else if(d < (1<<7)) {
1548         /* fixnum */
1549         char buf = take8_32(d);
1550         append_buffer(&buf, 1);
1551     } else {
1552         if(d < (1<<8)) {
1553             /* unsigned 8 */
1554             char buf[2] = { static_cast<char>(0xccu), take8_32(d)};
1555             append_buffer(buf, 2);
1556         } else if(d < (1<<16)) {
1557             /* unsigned 16 */
1558             char buf[3];
1559             buf[0] = static_cast<char>(0xcdu); _msgpack_store16(&buf[1], static_cast<uint16_t>(d));
1560             append_buffer(buf, 3);
1561         } else {
1562             /* unsigned 32 */
1563             char buf[5];
1564             buf[0] = static_cast<char>(0xceu); _msgpack_store32(&buf[1], static_cast<uint32_t>(d));
1565             append_buffer(buf, 5);
1566         }
1567     }
1568 }
1569 
1570 template <typename Stream>
1571 template <typename T>
1572 inline void packer<Stream>::pack_imp_int64(T d)
1573 {
1574     if(d < -(1LL<<5)) {
1575         if(d < -(1LL<<15)) {
1576             if(d < -(1LL<<31)) {
1577                 /* signed 64 */
1578                 char buf[9];
1579                 buf[0] = static_cast<char>(0xd3u); _msgpack_store64(&buf[1], d);
1580                 append_buffer(buf, 9);
1581             } else {
1582                 /* signed 32 */
1583                 char buf[5];
1584                 buf[0] = static_cast<char>(0xd2u); _msgpack_store32(&buf[1], static_cast<int32_t>(d));
1585                 append_buffer(buf, 5);
1586             }
1587         } else {
1588             if(d < -(1<<7)) {
1589                 /* signed 16 */
1590                 char buf[3];
1591                 buf[0] = static_cast<char>(0xd1u); _msgpack_store16(&buf[1], static_cast<int16_t>(d));
1592                 append_buffer(buf, 3);
1593             } else {
1594                 /* signed 8 */
1595                 char buf[2] = {static_cast<char>(0xd0u), take8_64(d)};
1596                 append_buffer(buf, 2);
1597             }
1598         }
1599     } else if(d < (1<<7)) {
1600         /* fixnum */
1601         char buf = take8_64(d);
1602         append_buffer(&buf, 1);
1603     } else {
1604         if(d < (1LL<<16)) {
1605             if(d < (1<<8)) {
1606                 /* unsigned 8 */
1607                 char buf[2] = {static_cast<char>(0xccu), take8_64(d)};
1608                 append_buffer(buf, 2);
1609             } else {
1610                 /* unsigned 16 */
1611                 char buf[3];
1612                 buf[0] = static_cast<char>(0xcdu); _msgpack_store16(&buf[1], static_cast<uint16_t>(d));
1613                 append_buffer(buf, 3);
1614             }
1615         } else {
1616             if(d < (1LL<<32)) {
1617                 /* unsigned 32 */
1618                 char buf[5];
1619                 buf[0] = static_cast<char>(0xceu); _msgpack_store32(&buf[1], static_cast<uint32_t>(d));
1620                 append_buffer(buf, 5);
1621             } else {
1622                 /* unsigned 64 */
1623                 char buf[9];
1624                 buf[0] = static_cast<char>(0xcfu); _msgpack_store64(&buf[1], d);
1625                 append_buffer(buf, 9);
1626             }
1627         }
1628     }
1629 }
1630 
1631 /// @cond
1632 }  // MSGPACK_API_VERSION_NAMESPACE(v1)
1633 /// @endcond
1634 
1635 }  // namespace msgpack
1636 
1637 #endif // MSGPACK_V1_PACK_HPP
1638