utf8splitter.cpp
1 //------------------------------------------------------------------------------
2 // utf8splitter.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301, USA.
19 //
20 //------------------------------------------------------------------------------
21 // Copyright (C) 2014 "Zalewa" <zalewapl@gmail.com>
22 //------------------------------------------------------------------------------
23 #include "utf8splitter.h"
24 
25 #include <QDataStream>
26 
27 QList<QByteArray> Utf8Splitter::split(const QByteArray &in, int maxChunkLength)
28 {
29  QList<QByteArray> result;
30  QDataStream stream(in);
31  QByteArray largerChunk;
32  while (!stream.atEnd())
33  {
34  QByteArray chunk;
35  quint8 curByte;
36  stream >> curByte;
37  chunk.append(curByte);
38  if ((curByte & 0x80) != 0)
39  {
40  quint8 leading = curByte & 0xfc;
41  int numBytes = 0;
42  while ((leading & 0x80) != 0)
43  {
44  leading = leading << 1;
45  ++numBytes;
46  }
47  // When sub-bytes are appended to the chunk
48  // we already have 1 byte: the leading byte.
49  for (; numBytes > 1; --numBytes)
50  {
51  quint8 subByte;
52  stream >> subByte;
53  chunk.append(subByte);
54  }
55  }
56  if (largerChunk.size() + chunk.size() > maxChunkLength)
57  {
58  result << largerChunk;
59  largerChunk.clear();
60  }
61  largerChunk.append(chunk);
62  }
63  if (!largerChunk.isEmpty())
64  {
65  result << largerChunk;
66  }
67  return result;
68 }