Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef NET_BASE_BIG_ENDIAN_H_
      6 #define NET_BASE_BIG_ENDIAN_H_
      7 
      8 #include "base/basictypes.h"
      9 #include "base/strings/string_piece.h"
     10 #include "net/base/net_export.h"
     11 
     12 namespace net {
     13 
     14 // Read an integer (signed or unsigned) from |buf| in Big Endian order.
     15 // Note: this loop is unrolled with -O1 and above.
     16 // NOTE(szym): glibc dns-canon.c and SpdyFrameBuilder use
     17 // ntohs(*(uint16_t*)ptr) which is potentially unaligned.
     18 // This would cause SIGBUS on ARMv5 or earlier and ARMv6-M.
     19 template<typename T>
     20 inline void ReadBigEndian(const char buf[], T* out) {
     21   *out = buf[0];
     22   for (size_t i = 1; i < sizeof(T); ++i) {
     23     *out <<= 8;
     24     // Must cast to uint8 to avoid clobbering by sign extension.
     25     *out |= static_cast<uint8>(buf[i]);
     26   }
     27 }
     28 
     29 // Write an integer (signed or unsigned) |val| to |buf| in Big Endian order.
     30 // Note: this loop is unrolled with -O1 and above.
     31 template<typename T>
     32 inline void WriteBigEndian(char buf[], T val) {
     33   for (size_t i = 0; i < sizeof(T); ++i) {
     34     buf[sizeof(T)-i-1] = static_cast<char>(val & 0xFF);
     35     val >>= 8;
     36   }
     37 }
     38 
     39 // Specializations to make clang happy about the (dead code) shifts above.
     40 template<>
     41 inline void ReadBigEndian<uint8>(const char buf[], uint8* out) {
     42   *out = buf[0];
     43 }
     44 
     45 template<>
     46 inline void WriteBigEndian<uint8>(char buf[], uint8 val) {
     47   buf[0] = static_cast<char>(val);
     48 }
     49 
     50 // Allows reading integers in network order (big endian) while iterating over
     51 // an underlying buffer. All the reading functions advance the internal pointer.
     52 class NET_EXPORT BigEndianReader {
     53  public:
     54   BigEndianReader(const void* buf, size_t len);
     55 
     56   const char* ptr() const { return ptr_; }
     57   int remaining() const { return end_ - ptr_; }
     58 
     59   bool Skip(size_t len);
     60   bool ReadBytes(void* out, size_t len);
     61   // Creates a StringPiece in |out| that points to the underlying buffer.
     62   bool ReadPiece(base::StringPiece* out, size_t len);
     63   bool ReadU8(uint8* value);
     64   bool ReadU16(uint16* value);
     65   bool ReadU32(uint32* value);
     66 
     67  private:
     68   // Hidden to promote type safety.
     69   template<typename T>
     70   bool Read(T* v);
     71 
     72   const char* ptr_;
     73   const char* end_;
     74 };
     75 
     76 // Allows writing integers in network order (big endian) while iterating over
     77 // an underlying buffer. All the writing functions advance the internal pointer.
     78 class NET_EXPORT BigEndianWriter {
     79  public:
     80   BigEndianWriter(void* buf, size_t len);
     81 
     82   char* ptr() const { return ptr_; }
     83   int remaining() const { return end_ - ptr_; }
     84 
     85   bool Skip(size_t len);
     86   bool WriteBytes(const void* buf, size_t len);
     87   bool WriteU8(uint8 value);
     88   bool WriteU16(uint16 value);
     89   bool WriteU32(uint32 value);
     90 
     91  private:
     92   // Hidden to promote type safety.
     93   template<typename T>
     94   bool Write(T v);
     95 
     96   char* ptr_;
     97   char* end_;
     98 };
     99 
    100 }  // namespace net
    101 
    102 #endif  // NET_BASE_BIG_ENDIAN_H_
    103 
    104