Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Endian Buffer Types

Boost , ,

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

Endian Home    Функции преобразования   Арифметические типы   Буферные типы   Выбор подхода

Contents
Introduction
Example
Limitations
Feature set
Enums and typedefs
Class template endian_buffer
    Synopsis
    Members
    Non-Members
FAQ
Design
C++11
Compilation

Introduction

Внутренний байтовый порядок арифметических типов традиционно называетсяэндианностью. См.Википедиядля полного изученияэндианности, включая определениябольшого эндианаималенького эндиана.

Заголовок<boost/endian/buffers.hpp>обеспечивает<endian_buffer>, портативный эндиан-целое двоичный шаблон класса буфера с контролем порядка байта, типа значения, размера и выравнивания, независимо от нативной эндианности платформы & # 39. Typedefs предоставляют простые в использовании имена для общих конфигураций.

Случаи использования в основном связаны с переносимостью данных, либо через файлы, либо через сетевые соединения, но эти держатели байтов также могут использоваться для уменьшения использования памяти, размера файла или сетевой активности, поскольку они обеспечивают двоичные числовые размеры, недоступные в противном случае.

Class endian_buffer is aimed at users who wish explicit control over when endianness conversions occur. It also serves as the base class for the endian_arithmetic class template, which is aimed at users who wish fully automatic endianness conversion and direct support for all normal arithmetic operations.

Example

Программа<example/endian_example.cpp>пишет двоичный файл, содержащий четырехбайтовые, большие и малые эндиановые целые числа:

#include <iostream>
#include <cstdio>
#include <boost/endian/buffers.hpp>  // see Synopsis below
#include <boost/static_assert.hpp>
using namespace boost::endian;
namespace 
{
  //  This is an extract from a very widely used GIS file format.
  //  Why the designer decided to mix big and little endians in
  //  the same file is not known. But this is a real-world format
  //  and users wishing to write low level code manipulating these
  //  files have to deal with the mixed endianness.
  struct header
  {
    big_int32_buf_t     file_code;
    big_int32_buf_t     file_length;
    little_int32_buf_t  version;
    little_int32_buf_t  shape_type;
  };
  const char* filename = "test.dat";
}
int main(int, char* [])
{
  header h;
  BOOST_STATIC_ASSERT(sizeof(h) == 16U);  // reality check
  
  h.file_code   = 0x01020304;
  h.file_length = sizeof(header);
  h.version     = 1;
  h.shape_type  = 0x01020304;
  //  Low-level I/O such as POSIX read/write or <cstdio>
  //  fread/fwrite is sometimes used for binary file operations
  //  when ultimate efficiency is important. Such I/O is often
  //  performed in some C++ wrapper class, but to drive home the
  //  point that endian integers are often used in fairly
  //  low-level code that does bulk I/O operations, <cstdio>
  //  fopen/fwrite is used for I/O in this example.
  std::FILE* fi = std::fopen(filename, "wb");  // MUST BE BINARY
  
  if (!fi)
  {
    std::cout << "could not open " << filename << '\n';
    return 1;
  }
  if (std::fwrite(&h, sizeof(header), 1, fi)!= 1)
  {
    std::cout << "write failure for " << filename << '\n';
    return 1;
  }
  std::fclose(fi);
  std::cout << "created file " << filename << '\n';
  return 0;
}

После составления и исполнения<example/endian_example.cpp>, шестнадцатеричный слив<test.dat>показывает:

01020304 00000010 01000000 04030201

Обратите внимание, что первые два 32-разрядных целых числа являются большими эндианами, а вторые два — маленькими эндианами, хотя машина, на которой это было составлено и запущено, была малоэндианной.

Limitations

Для этого требуется<<climits>><CHAR_BIT == 8>. Если<CHAR_BIT>является неким другим значением, то компиляция приведет к<#error>. Это ограничение существует, потому что при проектировании, внедрении, тестировании и документации учитывались только проблемы, связанные с 8-битными байтами, и не было представлено реальных вариантов использования для других размеров.

В C++03<endian_buffer>не соответствует требованиям для типов POD, поскольку имеет конструкторы, частные члены данных и базовый класс. Это означает, что общие случаи использования основаны на неопределенном поведении в том, что C++ Стандарт не гарантирует макет памяти для не-POD типов. Это не было проблемой на практике, так как все известные компиляторы C++ выкладывают память, как если бы< endian>были POD-типом. В C++11 можно указать конструктор по умолчанию как тривиальный, а частные члены данных и базовые классы больше не дисквалифицируют тип от типа POD. Таким образом, в C++11<endian_buffer>больше не будет полагаться на неопределенное поведение.

Feature set

  • Большой эндиан | малый эндиан | нативный эндиан байтовый порядок.
  • неподписанный
  • Неприсоединившийся
  • 1-8 байт (необязательный) | 1, 2, 4, 8 байт (выровненный)
  • Выбор типа ценности

Enums and typedefs

Предусмотрены два тематических перечня:

enum class order {big, little, native};
enum class align {no, yes}; 

Предоставляется один шаблон класса:

template <order Order, typename T, std::size_t Nbits,
  align Align = align::no>
class endian_buffer;

Типдефы, такие как<big_int32_buf_t>, обеспечивают удобные соглашения об именах для общих случаев использования:

Name Alignment Endianness Sign Sizes in bits (n)
big_intn_buf_t no big signed 8,16,24,32,40,48,56,64
big_uintn_buf_t no big unsigned 8,16,24,32,40,48,56,64
little_intn_buf_t no little signed 8,16,24,32,40,48,56,64
little_uintn_buf_t no little unsigned 8,16,24,32,40,48,56,64
native_intn_buf_t no native signed 8,16,24,32,40,48,56,64
native_uintn_buf_t no native unsigned 8,16,24,32,40,48,56,64
big_intn_buf_at yes big signed 8,16,32,64
big_uintn_buf_at yes big unsigned 8,16,32,64
little_intn_buf_at yes little signed 8,16,32,64
little_uintn_buf_at yes little unsigned 8,16,32,64

Невыровненные типы не заставляют компиляторы вставлять байты прокладки в классы и структуры. Это важная характеристика, которую можно использовать для минимизации потерянного пространства в памяти, файлах и сетевых передачах.

Предупреждение:Код, который используетзажигаемые типы, возможно, непортативный, потому что требования выравнивания различаются между аппаратными архитектурами и потому, что выравнивание может быть затронуто коммутаторами компилятора или прагмами. Например, выравнивание 64-битного целого числа может быть на 32-битной границе на 32-битной машине и на 64-битной границе на 64-битной машине. Кроме того, выровненные типы доступны только в архитектурах с 8, 16, 32 и 64-разрядными целыми типами.

Рекомендация:Предпочитают неприсоединившиеся типы буферов.

Рекомендация:Защитите себя от болезней выравнивания. Например:

static_assert(sizeof(containing_struct) == 12, "sizeof(containing_struct) is wrong"); 

Примечание:Однобайтовые большие и маленькие буферные типы имеют одинаковую компоновку на всех платформах, поэтому они никогда не обращают вспять эндианность. Они предоставляются для обеспечения универсального кода, а также для улучшения читаемости и поиска кода.

Class template endian_buffer

<endian_buffer>является держателем байта для арифметических типов с эндианностьюпользователя, типом значения, размером ивыравниванием.

Synopsis

#include <boost/endian/conversion.hpp
namespace boost
{
  namespace endian
  {
    //  C++11 features emulated if not available
   
    enum class align {no, yes};            
    template <order Order, class T, std::size_t Nbits,
      align Align = align::no>
    class endian_buffer
    {
    public:
      typedef T value_type;
      endian_buffer() noexcept = default;
      explicit endian_buffer(T v) noexcept;
      endian_buffer& operator=(T v) noexcept;
      value_type     value() const noexcept;
      const char*    data() const noexcept;
    protected:
      implementaton-defined  endian_value;  // for exposition only
    };
    
    //  stream inserter
    template <class charT, class traits, order Order, class T,
      std::size_t n_bits, align Align>
    std::basic_ostream<charT, traits>&
      operator<<(std::basic_ostream<charT, traits>& os,
        const endian_buffer<Order, T, n_bits, Align>& x);
    //  stream extractor 
    template <class charT, class traits, order Order, class T,
      std::size_t n_bits, align A>
    std::basic_istream<charT, traits>&
      operator>>(std::basic_istream<charT, traits>& is,
        endian_buffer<Order, T, n_bits, Align>& x);
    // typedefs  
    // unaligned big endian signed integer buffers
    typedef endian_buffer<order::big, int_least8_t, 8>        big_int8_buf_t;
    typedef endian_buffer<order::big, int_least16_t, 16>      big_int16_buf_t;
    typedef endian_buffer<order::big, int_least32_t, 24>      big_int24_buf_t;
    typedef endian_buffer<order::big, int_least32_t, 32>      big_int32_buf_t;
    typedef endian_buffer<order::big, int_least64_t, 40>      big_int40_buf_t;
    typedef endian_buffer<order::big, int_least64_t, 48>      big_int48_buf_t;
    typedef endian_buffer<order::big, int_least64_t, 56>      big_int56_buf_t;
    typedef endian_buffer<order::big, int_least64_t, 64>      big_int64_buf_t;
  
    // unaligned big endian unsigned integer buffers
    typedef endian_buffer<order::big, uint_least8_t, 8>       big_uint8_buf_t;
    typedef endian_buffer<order::big, uint_least16_t, 16>     big_uint16_buf_t;
    typedef endian_buffer<order::big, uint_least32_t, 24>     big_uint24_buf_t;
    typedef endian_buffer<order::big, uint_least32_t, 32>     big_uint32_buf_t;
    typedef endian_buffer<order::big, uint_least64_t, 40>     big_uint40_buf_t;
    typedef endian_buffer<order::big, uint_least64_t, 48>     big_uint48_buf_t;
    typedef endian_buffer<order::big, uint_least64_t, 56>     big_uint56_buf_t;
    typedef endian_buffer<order::big, uint_least64_t, 64>     big_uint64_buf_t;
  
    // unaligned little endian signed integer buffers
    typedef endian_buffer<order::little, int_least8_t, 8>     little_int8_buf_t;
    typedef endian_buffer<order::little, int_least16_t, 16>   little_int16_buf_t;
    typedef endian_buffer<order::little, int_least32_t, 24>   little_int24_buf_t;
    typedef endian_buffer<order::little, int_least32_t, 32>   little_int32_buf_t;
    typedef endian_buffer<order::little, int_least64_t, 40>   little_int40_buf_t;
    typedef endian_buffer<order::little, int_least64_t, 48>   little_int48_buf_t;
    typedef endian_buffer<order::little, int_least64_t, 56>   little_int56_buf_t;
    typedef endian_buffer<order::little, int_least64_t, 64>   little_int64_buf_t;
  
    // unaligned little endian unsigned integer buffers
    typedef endian_buffer<order::little, uint_least8_t, 8>    little_uint8_buf_t;
    typedef endian_buffer<order::little, uint_least16_t, 16>  little_uint16_buf_t;
    typedef endian_buffer<order::little, uint_least32_t, 24>  little_uint24_buf_t;
    typedef endian_buffer<order::little, uint_least32_t, 32>  little_uint32_buf_t;
    typedef endian_buffer<order::little, uint_least64_t, 40>  little_uint40_buf_t;
    typedef endian_buffer<order::little, uint_least64_t, 48>  little_uint48_buf_t;
    typedef endian_buffer<order::little, uint_least64_t, 56>  little_uint56_buf_t;
    typedef endian_buffer<order::little, uint_least64_t, 64>  little_uint64_buf_t;
  
    // unaligned native endian signed integer types
    typedef implementation-defined_int8_buf_t   native_int8_buf_t;
    typedef implementation-defined_int16_buf_t  native_int16_buf_t;
    typedef implementation-defined_int24_buf_t  native_int24_buf_t;
    typedef implementation-defined_int32_buf_t  native_int32_buf_t;
    typedef implementation-defined_int40_buf_t  native_int40_buf_t;
    typedef implementation-defined_int48_buf_t  native_int48_buf_t;
    typedef implementation-defined_int56_buf_t  native_int56_buf_t;
    typedef implementation-defined_int64_buf_t  native_int64_buf_t;
    // unaligned native endian unsigned integer types
    typedef implementation-defined_uint8_buf_t   native_uint8_buf_t;
    typedef implementation-defined_uint16_buf_t  native_uint16_buf_t;
    typedef implementation-defined_uint24_buf_t  native_uint24_buf_t;
    typedef implementation-defined_uint32_buf_t  native_uint32_buf_t;
    typedef implementation-defined_uint40_buf_t  native_uint40_buf_t;
    typedef implementation-defined_uint48_buf_t  native_uint48_buf_t;
    typedef implementation-defined_uint56_buf_t  native_uint56_buf_t;
    typedef implementation-defined_uint64_buf_t  native_uint64_buf_t;
    
    // aligned big endian signed integer buffers
    typedef endian_buffer<order::big, int8_t, 8, align::yes>       big_int8_buf_at;
    typedef endian_buffer<order::big, int16_t, 16, align::yes>     big_int16_buf_at;
    typedef endian_buffer<order::big, int32_t, 32, align::yes>     big_int32_buf_at;
    typedef endian_buffer<order::big, int64_t, 64, align::yes>     big_int64_buf_at;
  
    // aligned big endian unsigned integer buffers
    typedef endian_buffer<order::big, uint8_t, 8, align::yes>      big_uint8_buf_at;
    typedef endian_buffer<order::big, uint16_t, 16, align::yes>    big_uint16_buf_at;
    typedef endian_buffer<order::big, uint32_t, 32, align::yes>    big_uint32_buf_at;
    typedef endian_buffer<order::big, uint64_t, 64, align::yes>    big_uint64_buf_at;
  
    // aligned little endian signed integer buffers
    typedef endian_buffer<order::little, int8_t, 8, align::yes>    little_int8_buf_at;
    typedef endian_buffer<order::little, int16_t, 16, align::yes>  little_int16_buf_at;
    typedef endian_buffer<order::little, int32_t, 32, align::yes>  little_int32_buf_at;
    typedef endian_buffer<order::little, int64_t, 64, align::yes>  little_int64_buf_at;
  
    // aligned little endian unsigned integer buffers
    typedef endian_buffer<order::little, uint8_t, 8, align::yes>   little_uint8_buf_at;
    typedef endian_buffer<order::little, uint16_t, 16, align::yes> little_uint16_buf_at;
    typedef endian_buffer<order::little, uint32_t, 32, align::yes> little_uint32_buf_at;
    typedef endian_buffer<order::little, uint64_t, 64, align::yes> little_uint64_buf_at;
    // aligned native endian typedefs are not provided because
    // <cstdint> types are superior for this use case
  
  } // namespace endian
} // namespace boost

Текст<implementation-defined>в типоразмерах выше либо<big>, либо<little>в соответствии с родной эндианностью платформы.

Экспозиторный элемент данных<endian_value>сохраняет текущее значение объекта<endian_value>в виде последовательности байтов, упорядоченных в соответствии с параметром шаблона<Order>. Тип< implementation-defined><endian_value>- это тип<char[Nbits/CHAR_BIT]>или<T>, который соответствует требованиям, предъявляемым параметрами шаблона<Nbits>и<Align>.   Макро<CHAR_BIT>определено в<<climits>>. Единственное значение<CHAR_BIT>, которое необходимо поддерживать, составляет 8.

Параметр шаблона<T>должен быть стандартным целым типом (C++std, 3.9.1) и< sizeof(T)*CHAR_BIT>должен быть больше или равен<Nbits>.

Members

endian_buffer() noexcept = default;

Эффекты:Построение неинициализированного объекта типа<endian_buffer<Order, T, Nbits, Align>>.

explicit endian_buffer(T v) noexcept;

Эффекты:Конструирует объект типа<endian_buffer<Order, T, Nbits, Align>>.

Постусловие:<value() == v & mask>, где<mask>является константой типа<value_type>с<Nbits>битами низкого порядка, установленными на один.

Замечания:Если<Align>является<align::yes>, то преобразование эндианности, если требуется, выполняется< boost::endian::endian_reverse>.

endian_buffer& operator=(T v) noexcept;

Постусловие:<value() == v & mask>, где<mask>является константой типа<value_type>с<Nbits>битами низкого порядка, установленными на один.

Возвращение:<*this>.

Замечания:Если<Align>является<align::yes>, то преобразование эндианности, если требуется, выполняется< boost::endian::endian_reverse>.

value_type value() const noexcept;

Возвращается:<endian_value>, преобразуется в<value_type>, если требуется, и имеет эндианность родной платформы.

Замечания:Если<Align>является<align::yes>, то преобразование эндианности, если требуется, выполняется< boost::endian::endian_reverse>.

const char* data() const noexcept;

Возврат:Указатель на первый байт<endian_value>.

Non-member functions

template <class charT, class traits, order Order, class T,
  std::size_t n_bits, align Align>
std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os,
  const endian_buffer<Order, T, n_bits, Align>& x);

Возвращение:<os << x.value()>.

template <class charT, class traits, order Order, class T,
  std::size_t n_bits, align A>
std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is,
  endian_buffer<Order, T, n_bits, Align>& x);

Эффекты:Как будто:

T i;
if (is >> i)
  x = i;

Возвращение:<is>.

FAQ

См. домашнюю страницуEndianFAQ для FAQ в библиотеке.

Почему бы просто не использовать Boost.Serialization?Сериализация включает в себя преобразование для каждого объекта, участвующего в I/O. Эндиевые целые числа не требуют преобразования или копирования. Они уже в нужном формате для двоичного ввода/вывода. Таким образом, их можно читать или писать навалом.

Являются ли эндианские типы POD?Да, для C++11. Нет для C++03, хотя несколькомакросовдоступны для форсирования PODness во всех случаях.

Каковы последствия того, что целые типы эндиев не являются POD с компиляторами C++03?Они не могут использоваться в профсоюзах. Кроме того, компиляторы не обязаны выравнивать или размещать хранилище портативными способами, хотя эта потенциальная проблема не помешала использованию Boost. Эндиан с реальными компиляторами.

Что хорошего вродномэндианстве?Он обеспечивает выравнивание и гарантии размера, недоступные для встроенных типов. Упрощает общее программирование.

Зачем беспокоиться о выровненных типах эндиев?Выровненные целые операции могут быть быстрее (в 10-20 раз быстрее), если эндианность и выравнивание типа соответствуют требованиям эндианности и выравнивания машины. Код, однако, вероятно, будет несколько менее портативным, чем с неприсоединившимися типами.

Design considerations for Boost.Endian buffers

  • Должна быть пригодна для ввода/вывода - другими словами, должна быть мемкопируемой.
  • Необходимо точно указать размер и внутренний байт заказа.
  • Должен работать правильно, когда внутреннее целое представление имеет больше битов, чем сумма битов во внешнем представлении байта. Расширение знака должно работать правильно, когда тип представления внутреннего целого числа имеет больше битов, чем сумма битов во внешних байтах. Например, использование 64-битного целого числа внутри для представления 40-битных (5 байт) чисел должно работать как для положительных, так и для отрицательных значений.
  • Должен работать правильно (включая использование одного и того же определенного внешнего представления) независимо от того, относится ли компилятор к char как к подписанному или неподписанному.
  • Несогласованные типы не должны заставлять компиляторы вставлять байты прокладки.
  • Реализация должна обеспечить оптимизацию с большой осторожностью. Опыт показал, что оптимизация целых чисел часто становится пессимизацией при смене машин или компиляторов. Пессимизации также могут происходить при изменении коммутаторов компилятора, версий компилятора или моделей процессоров той же архитектуры.

C++11

Доступность функции C++11Defaulted Functionsобнаруживается автоматически и будет использоваться, если она присутствует, для обеспечения того, чтобы объекты<class endian_buffer>были тривиальными и, следовательно, POD.

Compilation

Повышаю. Endian полностью реализован в заголовках, без необходимости ссылаться на какие-либо библиотеки объектов Boost.

Несколько макросов позволяют пользователю контролировать функции:

  • BOOST_ENDIAN_NO_CTORS (0) не имеет строителей. Предполагаемое использование предназначено для компиляции пользовательского кода, который должен быть портативным между компиляторами независимо от поддержки C++11Defaulted Functions. Использование конструкторов всегда будет неудачным
    .
  • BOOST_ENDIAN_FORCE_PODNESS BOOST_ENDIAN_NO_CTORS определяется, если компилятор не поддерживает C++11. Это гарантирует, что объектыclass endian_bufferявляются POD, и поэтому могут использоваться в союзах C++03. В C++11class endian_bufferобъекты являются POD, хотя у них есть конструкторы, поэтому их всегда можно использовать в союзах.

Последнее изменение:14 октября 201514 October, 2015[ORIG_END] -->

© Copyright Beman Dawes, 2006-2009, 2013

Распространяется в соответствии с Лицензией на программное обеспечение Boost, версия 1.0. См.www.boost.org/ LICENSE_1_0.txt

Статья Endian Buffer Types раздела может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-20 04:46:19/0.0061020851135254/0