180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006 The Android Open Source Project 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifndef SkEndian_DEFINED 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkEndian_DEFINED 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTypes.h" 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** \file SkEndian.h 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Macros and helper functions for handling 16 and 32 bit values in 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru big and little endian formats. 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN) 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #error "can't have both LENDIAN and BENDIAN defined" 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN) 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #error "need either LENDIAN or BENDIAN defined" 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** Swap the two bytes in the low 16bits of the parameters. 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru e.g. 0x1234 -> 0x3412 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline uint16_t SkEndianSwap16(U16CPU value) { 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(value == (uint16_t)value); 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return static_cast<uint16_t>((value >> 8) | (value << 8)); 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutemplate<uint16_t N> struct SkTEndianSwap16 { 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static const uint16_t value = static_cast<uint16_t>((N >> 8) | ((N & 0xFF) << 8)); 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** Vector version of SkEndianSwap16(), which swaps the 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru low two bytes of each value in the array. 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline void SkEndianSwap16s(uint16_t array[], int count) { 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(count == 0 || array != NULL); 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (--count >= 0) { 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *array = SkEndianSwap16(*array); 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru array += 1; 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** Reverse all 4 bytes in a 32bit value. 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru e.g. 0x12345678 -> 0x78563412 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline uint32_t SkEndianSwap32(uint32_t value) { 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return ((value & 0xFF) << 24) | 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru ((value & 0xFF00) << 8) | 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru ((value & 0xFF0000) >> 8) | 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (value >> 24); 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutemplate<uint32_t N> struct SkTEndianSwap32 { 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static const uint32_t value = ((N & 0xFF) << 24) | 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru ((N & 0xFF00) << 8) | 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru ((N & 0xFF0000) >> 8) | 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (N >> 24); 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/** Vector version of SkEndianSwap32(), which swaps the 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bytes of each value in the array. 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline void SkEndianSwap32s(uint32_t array[], int count) { 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(count == 0 || array != NULL); 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (--count >= 0) { 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *array = SkEndianSwap32(*array); 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru array += 1; 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/** Reverse all 8 bytes in a 64bit value. 817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger e.g. 0x1122334455667788 -> 0x8877665544332211 827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger*/ 837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic inline uint64_t SkEndianSwap64(uint64_t value) { 847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return (((value & 0x00000000000000FFULL) << (8*7)) | 857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger ((value & 0x000000000000FF00ULL) << (8*5)) | 867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger ((value & 0x0000000000FF0000ULL) << (8*3)) | 877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger ((value & 0x00000000FF000000ULL) << (8*1)) | 887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger ((value & 0x000000FF00000000ULL) >> (8*1)) | 897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger ((value & 0x0000FF0000000000ULL) >> (8*3)) | 907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger ((value & 0x00FF000000000000ULL) >> (8*5)) | 917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger ((value) >> (8*7))); 927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergertemplate<uint64_t N> struct SkTEndianSwap64 { 947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger static const uint64_t value = (((N & 0x00000000000000FFULL) << (8*7)) | 957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger ((N & 0x000000000000FF00ULL) << (8*5)) | 967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger ((N & 0x0000000000FF0000ULL) << (8*3)) | 977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger ((N & 0x00000000FF000000ULL) << (8*1)) | 987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger ((N & 0x000000FF00000000ULL) >> (8*1)) | 997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger ((N & 0x0000FF0000000000ULL) >> (8*3)) | 1007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger ((N & 0x00FF000000000000ULL) >> (8*5)) | 1017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger ((N) >> (8*7))); 1027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}; 1037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/** Vector version of SkEndianSwap64(), which swaps the 1057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bytes of each value in the array. 1067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger*/ 1077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic inline void SkEndianSwap64s(uint64_t array[], int count) { 1087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkASSERT(count == 0 || array != NULL); 1097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger while (--count >= 0) { 1117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *array = SkEndianSwap64(*array); 1127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger array += 1; 1137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 1147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 1157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_CPU_LENDIAN 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkEndian_SwapBE16(n) SkEndianSwap16(n) 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkEndian_SwapBE32(n) SkEndianSwap32(n) 1197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger #define SkEndian_SwapBE64(n) SkEndianSwap64(n) 12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkEndian_SwapLE16(n) (n) 12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkEndian_SwapLE32(n) (n) 1227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger #define SkEndian_SwapLE64(n) (n) 12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkTEndian_SwapBE16(n) SkTEndianSwap16<n>::value 12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkTEndian_SwapBE32(n) SkTEndianSwap32<n>::value 1267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger #define SkTEndian_SwapBE64(n) SkTEndianSwap64<n>::value 12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkTEndian_SwapLE16(n) (n) 12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkTEndian_SwapLE32(n) (n) 1297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger #define SkTEndian_SwapLE64(n) (n) 13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else // SK_CPU_BENDIAN 13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkEndian_SwapBE16(n) (n) 13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkEndian_SwapBE32(n) (n) 1337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger #define SkEndian_SwapBE64(n) (n) 13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkEndian_SwapLE16(n) SkEndianSwap16(n) 13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkEndian_SwapLE32(n) SkEndianSwap32(n) 1367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger #define SkEndian_SwapLE64(n) SkEndianSwap64(n) 13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkTEndian_SwapBE16(n) (n) 13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkTEndian_SwapBE32(n) (n) 1407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger #define SkTEndian_SwapBE64(n) (n) 14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkTEndian_SwapLE16(n) SkTEndianSwap16<n>::value 14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkTEndian_SwapLE32(n) SkTEndianSwap32<n>::value 1437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger #define SkTEndian_SwapLE64(n) SkTEndianSwap64<n>::value 14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// When a bytestream is embedded in a 32-bit word, how far we need to 14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// shift the word to extract each byte from the low 8 bits by anding with 0xff. 14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_CPU_LENDIAN 14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkEndian_Byte0Shift 0 15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkEndian_Byte1Shift 8 15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkEndian_Byte2Shift 16 15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkEndian_Byte3Shift 24 15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else // SK_CPU_BENDIAN 15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkEndian_Byte0Shift 24 15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkEndian_Byte1Shift 16 15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkEndian_Byte2Shift 8 15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkEndian_Byte3Shift 0 15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if defined(SK_UINT8_BITFIELD_LENDIAN) && defined(SK_UINT8_BITFIELD_BENDIAN) 16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #error "can't have both bitfield LENDIAN and BENDIAN defined" 16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if !defined(SK_UINT8_BITFIELD_LENDIAN) && !defined(SK_UINT8_BITFIELD_BENDIAN) 16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #ifdef SK_CPU_LENDIAN 16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SK_UINT8_BITFIELD_LENDIAN 16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #else 16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SK_UINT8_BITFIELD_BENDIAN 17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #endif 17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_UINT8_BITFIELD_LENDIAN 17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SK_UINT8_BITFIELD(f0, f1, f2, f3, f4, f5, f6, f7) \ 17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_OT_BYTE f0 : 1; \ 17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_OT_BYTE f1 : 1; \ 17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_OT_BYTE f2 : 1; \ 17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_OT_BYTE f3 : 1; \ 17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_OT_BYTE f4 : 1; \ 18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_OT_BYTE f5 : 1; \ 18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_OT_BYTE f6 : 1; \ 18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_OT_BYTE f7 : 1; 18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SK_UINT8_BITFIELD(f0, f1, f2, f3, f4, f5, f6, f7) \ 18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_OT_BYTE f7 : 1; \ 18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_OT_BYTE f6 : 1; \ 18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_OT_BYTE f5 : 1; \ 18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_OT_BYTE f4 : 1; \ 18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_OT_BYTE f3 : 1; \ 19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_OT_BYTE f2 : 1; \ 19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_OT_BYTE f1 : 1; \ 19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_OT_BYTE f0 : 1; 19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 196