1// Copyright (c) 2010, Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10//     * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14//     * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30#include <arpa/inet.h>
31#include <limits.h>
32
33#include <string>
34#include <vector>
35
36#include "common/using_std_string.h"
37#include "processor/binarystream.h"
38
39namespace google_breakpad {
40using std::vector;
41
42binarystream &binarystream::operator>>(string &str) {
43  uint16_t length;
44  *this >> length;
45  if (eof())
46    return *this;
47  if (length == 0) {
48    str.clear();
49    return *this;
50  }
51  vector<char> buffer(length);
52  stream_.read(&buffer[0], length);
53  if (!eof())
54    str.assign(&buffer[0], length);
55  return *this;
56}
57
58binarystream &binarystream::operator>>(uint8_t &u8) {
59  stream_.read((char *)&u8, 1);
60  return *this;
61}
62
63binarystream &binarystream::operator>>(uint16_t &u16) {
64  uint16_t temp;
65  stream_.read((char *)&temp, 2);
66  if (!eof())
67    u16 = ntohs(temp);
68  return *this;
69}
70
71binarystream &binarystream::operator>>(uint32_t &u32) {
72  uint32_t temp;
73  stream_.read((char *)&temp, 4);
74  if (!eof())
75    u32 = ntohl(temp);
76  return *this;
77}
78
79binarystream &binarystream::operator>>(uint64_t &u64) {
80  uint32_t lower, upper;
81  *this >> lower >> upper;
82  if (!eof())
83    u64 = static_cast<uint64_t>(lower) | (static_cast<uint64_t>(upper) << 32);
84  return *this;
85}
86
87binarystream &binarystream::operator<<(const string &str) {
88  if (str.length() > USHRT_MAX) {
89    // truncate to 16-bit length
90    *this << static_cast<uint16_t>(USHRT_MAX);
91    stream_.write(str.c_str(), USHRT_MAX);
92  } else {
93    *this << (uint16_t)(str.length() & 0xFFFF);
94    stream_.write(str.c_str(), str.length());
95  }
96  return *this;
97}
98
99binarystream &binarystream::operator<<(uint8_t u8) {
100  stream_.write((const char*)&u8, 1);
101  return *this;
102}
103
104binarystream &binarystream::operator<<(uint16_t u16) {
105  u16 = htons(u16);
106  stream_.write((const char*)&u16, 2);
107  return *this;
108}
109
110binarystream &binarystream::operator<<(uint32_t u32) {
111  u32 = htonl(u32);
112  stream_.write((const char*)&u32, 4);
113  return *this;
114}
115
116binarystream &binarystream::operator<<(uint64_t u64) {
117  // write 64-bit ints as two 32-bit ints, so we can byte-swap them easily
118  uint32_t lower = static_cast<uint32_t>(u64 & 0xFFFFFFFF);
119  uint32_t upper = static_cast<uint32_t>(u64 >> 32);
120  *this << lower << upper;
121  return *this;
122}
123
124}  // namespace google_breakpad
125