1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #ifndef HIDUTIL_STREAM_IO_UTIL_H_ 17 #define HIDUTIL_STREAM_IO_UTIL_H_ 18 19 #include "HidLog.h" 20 #include <istream> 21 #include <iomanip> 22 #include <sstream> 23 #include <vector> 24 #include <cassert> 25 26 namespace HidUtil { 27 28 template<typename CharT> 29 class charvectorbuf : public std::streambuf { // class name is consistent with std lib 30 static_assert(std::is_const<CharT>::value == false, "cannot use const type"); 31 public: 32 // r/w buffer constructors 33 charvectorbuf(std::vector<CharT> &vec) { 34 init(vec.data(), vec.size()); 35 } 36 37 charvectorbuf(CharT *begin, CharT *end) { 38 assert(end >= begin); 39 init(begin, end - begin); 40 } 41 42 charvectorbuf(CharT *begin, size_t size) { 43 init(begin, size); 44 } 45 46 // r/o buffer constructor 47 charvectorbuf(const std::vector<CharT> &vec) { 48 init(vec.data(), vec.size()); 49 } 50 51 charvectorbuf(const CharT *begin, const CharT *end) { 52 assert(end >= begin); 53 init(begin, end - begin); 54 } 55 56 charvectorbuf(const CharT *begin, size_t size) { 57 init(begin, size); 58 } 59 protected: 60 virtual std::streampos seekpos( 61 std::streampos sp, std::ios_base::openmode which = 62 std::ios_base::in | std::ios_base::out) override { 63 return seekoff(std::streamoff(sp), std::ios_base::beg, which); 64 } 65 66 // this is needed to use ftell() on stream 67 virtual std::streampos seekoff( 68 std::streamoff off, std::ios_base::seekdir way, 69 std::ios_base::openmode which = 70 std::ios_base::in | std::ios_base::out) override { 71 72 // pptr() == nullptr: read-only 73 assert(pptr() == nullptr || egptr() - eback() == epptr() - pbase()); 74 bool in = which & std::ios_base::in; 75 bool out = which & std::ios_base::out; 76 pos_type end = egptr() - eback(); 77 78 if (!in && !out) { 79 return pos_type(-1); 80 } 81 82 if (in && out && way == std::ios_base::cur) { 83 return pos_type(-1); 84 } 85 86 off_type noff; 87 switch (way) { 88 case std::ios_base::beg: 89 noff = 0; 90 break; 91 case std::ios_base::cur: 92 if (in) { 93 noff = gptr() - eback(); 94 } else { 95 noff = pptr() - pbase(); 96 } 97 break; 98 case std::ios_base::end: 99 noff = end; 100 break; 101 default: 102 return pos_type(-1); 103 } 104 noff += off; 105 if (noff < 0 || noff > end) { 106 return pos_type(-1); 107 } 108 109 if (noff != 0 && ((in && gptr() == nullptr) || (out && pptr() == nullptr))) { 110 return pos_type(-1); 111 } 112 113 if (in) { 114 setg(eback(), eback() + noff, egptr()); 115 } 116 117 if (out) { 118 setp(pbase(), epptr()); 119 pbump(noff); 120 } 121 122 return pos_type(noff); 123 } 124 private: 125 // read only buffer init 126 void init(const CharT *base, size_t size) { 127 setg((char*)base, (char*)base, (char*)(base + size)); 128 } 129 130 // read write buffer init 131 void init(CharT *base, size_t size) { 132 setg((char*)base, (char*)base, (char*)(base + size)); 133 setp((char*)base, (char*)(base + size)); 134 } 135 }; 136 137 // dump binary values 138 template <class ForwardIterator> 139 void hexdumpToStream(std::ostream &os, const ForwardIterator &first, const ForwardIterator &last) { 140 static_assert( 141 std::is_convertible< 142 typename std::iterator_traits<ForwardIterator>::iterator_category, 143 std::forward_iterator_tag>::value 144 && std::is_convertible< 145 typename std::iterator_traits<ForwardIterator>::value_type, 146 unsigned char>::value 147 && sizeof(typename std::iterator_traits<ForwardIterator>::value_type) 148 == sizeof(unsigned char), 149 "Only accepts forward iterator of a type of size 1 " 150 "that can be convert to unsigned char.\n"); 151 size_t c = 0; 152 std::ostringstream ss; 153 for (ForwardIterator i = first; i != last; ++i, ++c) { 154 unsigned char v = *i; 155 // formatting 156 switch (c & 0xf) { 157 case 0: 158 // address 159 os << ss.str() << LOG_ENDL; 160 ss.str(""); 161 ss << std::hex; 162 ss << std::setfill('0') << std::setw(4) << c << ": "; 163 break; 164 case 8: 165 // space 166 ss << " "; 167 break; 168 } 169 ss << std::setfill('0') << std::setw(2) 170 << static_cast<unsigned>(static_cast<unsigned char>(v)) << " "; 171 } 172 os << ss.str() << LOG_ENDL; 173 } 174 } //namespace HidUtil 175 176 #endif // HIDUTIL_STREAM_IO_UTIL_H_ 177 178