Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-15 09:16:30

0001 // Created on: 2013-01-28
0002 // Created by: Kirill GAVRILOV
0003 // Copyright (c) 2013-2014 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef NCollection_UtfIterator_HeaderFile
0017 #define NCollection_UtfIterator_HeaderFile
0018 
0019 #include <Standard_Handle.hxx>
0020 
0021 //! Template class for Unicode strings support.
0022 //!
0023 //! It defines an iterator and provide correct way to read multi-byte text (UTF-8 and UTF-16)
0024 //! and convert it from one to another.
0025 //! The current value of iterator is returned as UTF-32 Unicode symbol.
0026 //!
0027 //! Here and below term "Unicode symbol" is used as
0028 //! synonym of "Unicode code point".
0029 template <typename Type>
0030 class NCollection_UtfIterator
0031 {
0032 
0033 public:
0034   //! Constructor.
0035   //! @param theString buffer to iterate
0036   NCollection_UtfIterator(const Type* theString)
0037       : myPosition(theString),
0038         myPosNext(theString),
0039         myCharIndex(0),
0040         myCharUtf32(0)
0041   {
0042     if (theString != nullptr)
0043     {
0044       ++(*this);
0045       myCharIndex = 0;
0046     }
0047   }
0048 
0049   //! Initialize iterator within specified NULL-terminated string.
0050   void Init(const Type* theString)
0051   {
0052     myPosition  = theString;
0053     myPosNext   = theString;
0054     myCharUtf32 = 0;
0055     if (theString != nullptr)
0056     {
0057       ++(*this);
0058     }
0059     myCharIndex = 0;
0060   }
0061 
0062   //! Pre-increment operator. Reads the next unicode symbol.
0063   //! Notice - no protection against overrun!
0064   NCollection_UtfIterator& operator++()
0065   {
0066     myPosition = myPosNext;
0067     ++myCharIndex;
0068     readNext(static_cast<const typename CharTypeChooser<Type>::type*>(nullptr));
0069     return *this;
0070   }
0071 
0072   //! Post-increment operator.
0073   //! Notice - no protection against overrun!
0074   NCollection_UtfIterator operator++(int)
0075   {
0076     NCollection_UtfIterator aCopy = *this;
0077     ++*this;
0078     return aCopy;
0079   }
0080 
0081   //! Equality operator.
0082   constexpr bool operator==(const NCollection_UtfIterator& theRight) const noexcept
0083   {
0084     return myPosition == theRight.myPosition;
0085   }
0086 
0087   //! Return true if Unicode symbol is within valid range.
0088   constexpr bool IsValid() const noexcept { return myCharUtf32 <= UTF32_MAX_LEGAL; }
0089 
0090   //! Dereference operator.
0091   //! @return the UTF-32 codepoint of the symbol currently pointed by iterator.
0092   constexpr char32_t operator*() const noexcept { return myCharUtf32; }
0093 
0094   //! Buffer-fetching getter.
0095   constexpr const Type* BufferHere() const noexcept { return myPosition; }
0096 
0097   //! Buffer-fetching getter. Dangerous! Iterator should be reinitialized on buffer change.
0098   Type* ChangeBufferHere() noexcept { return (Type*)myPosition; }
0099 
0100   //! Buffer-fetching getter.
0101   constexpr const Type* BufferNext() const noexcept { return myPosNext; }
0102 
0103   //! @return the index displacement from iterator initialization
0104   //!         (first symbol has index 0)
0105   constexpr int Index() const noexcept { return myCharIndex; }
0106 
0107   //! @return the advance in bytes to store current symbol in UTF-8.
0108   //! 0 means an invalid symbol;
0109   //! 1-4 bytes are valid range.
0110   int AdvanceBytesUtf8() const;
0111 
0112   //! @return the advance in bytes to store current symbol in UTF-16.
0113   //! 0 means an invalid symbol;
0114   //! 2 bytes is a general case;
0115   //! 4 bytes for surrogate pair.
0116   int AdvanceBytesUtf16() const;
0117 
0118   //! @return the advance in bytes to store current symbol in UTF-16.
0119   //! 0 means an invalid symbol;
0120   //! 1 16-bit code unit is a general case;
0121   //! 2 16-bit code units for surrogate pair.
0122   int AdvanceCodeUnitsUtf16() const;
0123 
0124   //! @return the advance in bytes to store current symbol in UTF-32.
0125   //! Always 4 bytes (method for consistency).
0126   constexpr int AdvanceBytesUtf32() const noexcept { return int(sizeof(char32_t)); }
0127 
0128   //! Fill the UTF-8 buffer within current Unicode symbol.
0129   //! Use method AdvanceUtf8() to allocate buffer with enough size.
0130   //! @param theBuffer buffer to fill
0131   //! @return new buffer position (for next char)
0132   char*          GetUtf8(char* theBuffer) const;
0133   unsigned char* GetUtf8(unsigned char* theBuffer) const;
0134 
0135   //! Fill the UTF-16 buffer within current Unicode symbol.
0136   //! Use method AdvanceUtf16() to allocate buffer with enough size.
0137   //! @param theBuffer buffer to fill
0138   //! @return new buffer position (for next char)
0139   char16_t* GetUtf16(char16_t* theBuffer) const;
0140 
0141   //! Fill the UTF-32 buffer within current Unicode symbol.
0142   //! Use method AdvanceUtf32() to allocate buffer with enough size.
0143   //! @param theBuffer buffer to fill
0144   //! @return new buffer position (for next char)
0145   char32_t* GetUtf32(char32_t* theBuffer) const;
0146 
0147   //! @return the advance in TypeWrite chars needed to store current symbol
0148   template <typename TypeWrite>
0149   inline int AdvanceBytesUtf() const
0150   {
0151     return advanceBytes(static_cast<const typename CharTypeChooser<TypeWrite>::type*>(nullptr));
0152   }
0153 
0154   //! Fill the UTF-** buffer within current Unicode symbol.
0155   //! Use method AdvanceUtf**() to allocate buffer with enough size.
0156   //! @param theBuffer buffer to fill
0157   //! @return new buffer position (for next char)
0158   template <typename TypeWrite>
0159   inline TypeWrite* GetUtf(TypeWrite* theBuffer) const
0160   {
0161     return (
0162       TypeWrite*)(getUtf(reinterpret_cast<typename CharTypeChooser<TypeWrite>::type*>(theBuffer)));
0163   }
0164 
0165 private:
0166   //! Helper template class dispatching its argument class
0167   //! to the equivalent (by size) character (Unicode code unit) type.
0168   //! The code unit type is defined as nested typedef "type".
0169   //!
0170   //! In practice this is relevant for wchar_t type:
0171   //! typename CharTypeChooser<wchar_t>::type resolves to
0172   //! char16_t on Windows and to char32_t on Linux.
0173   template <typename TypeChar>
0174   class CharTypeChooser
0175       : public std::conditional<
0176           sizeof(TypeChar) == 1,
0177           char,
0178           typename std::conditional<
0179             sizeof(TypeChar) == 2,
0180             char16_t,
0181             typename std::conditional<sizeof(TypeChar) == 4, char32_t, void>::type>::type>
0182   {
0183   };
0184 
0185   //! Helper function for reading a single Unicode symbol from the UTF-8 string.
0186   //! Updates internal state appropriately.
0187   void readUTF8();
0188 
0189   //! Helper function for reading a single Unicode symbol from the UTF-16 string.
0190   //! Updates internal state appropriately.
0191   void readUTF16();
0192 
0193   //! Helper overload methods to dispatch reading function depending on code unit size
0194   void readNext(const char*) { readUTF8(); }
0195 
0196   void readNext(const char16_t*) { readUTF16(); }
0197 
0198   void readNext(const char32_t*) noexcept { myCharUtf32 = *myPosNext++; }
0199 
0200   //! Helper overload methods to dispatch advance function depending on code unit size
0201   int advanceBytes(const char*) const { return AdvanceBytesUtf8(); }
0202 
0203   int advanceBytes(const char16_t*) const { return AdvanceBytesUtf16(); }
0204 
0205   constexpr int advanceBytes(const char32_t*) const noexcept { return AdvanceBytesUtf32(); }
0206 
0207   //! Helper overload methods to dispatch getter function depending on code unit size
0208   char* getUtf(char* theBuffer) const { return GetUtf8(theBuffer); }
0209 
0210   char16_t* getUtf(char16_t* theBuffer) const { return GetUtf16(theBuffer); }
0211 
0212   char32_t* getUtf(char32_t* theBuffer) const { return GetUtf32(theBuffer); }
0213 
0214 private: //! @name unicode magic numbers
0215   //! The first character in a UTF-8 sequence indicates how many bytes to read (among other things).
0216   static constexpr unsigned char UTF8_BYTES_MINUS_ONE[256] = {
0217     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0218     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0219     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0220     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0221     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0222     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0223     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0224     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
0225 
0226   //! Magic values subtracted from a buffer value during UTF-8 conversion.
0227   //! This table contains as many values as there might be trailing bytes in a UTF-8 sequence.
0228   static constexpr char32_t offsetsFromUTF8[6] =
0229     {0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, 0xFA082080UL, 0x82082080UL};
0230 
0231   //! The first character in a UTF-8 sequence indicates how many bytes to read.
0232   static constexpr unsigned char UTF8_FIRST_BYTE_MARK[7] =
0233     {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
0234 
0235   // Magic numbers for UTF encoding/decoding
0236   static constexpr char32_t UTF8_BYTE_MASK             = 0xBF;
0237   static constexpr char32_t UTF8_BYTE_MARK             = 0x80;
0238   static constexpr char32_t UTF16_SURROGATE_HIGH_START = 0xD800;
0239   static constexpr char32_t UTF16_SURROGATE_HIGH_END   = 0xDBFF;
0240   static constexpr char32_t UTF16_SURROGATE_LOW_START  = 0xDC00;
0241   static constexpr char32_t UTF16_SURROGATE_LOW_END    = 0xDFFF;
0242   static constexpr char32_t UTF16_SURROGATE_HIGH_SHIFT = 10;
0243   static constexpr char32_t UTF16_SURROGATE_LOW_BASE   = 0x0010000UL;
0244   static constexpr char32_t UTF16_SURROGATE_LOW_MASK   = 0x3FFUL;
0245   static constexpr char32_t UTF32_MAX_BMP              = 0x0000FFFFUL;
0246   static constexpr char32_t UTF32_MAX_LEGAL            = 0x0010FFFFUL;
0247 
0248 private:                   //! @name private fields
0249   const Type* myPosition;  //!< buffer position of the first element in the current symbol
0250   const Type* myPosNext;   //!< buffer position of the first element in the next symbol
0251   int         myCharIndex; //!< index displacement from iterator initialization
0252   char32_t    myCharUtf32; //!< Unicode symbol stored at the current buffer position
0253 };
0254 
0255 // template implementation
0256 #include <NCollection_UtfIterator.lxx>
0257 
0258 #endif // _NCollection_UtfIterator_H__