Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit355d908

Browse files
Added utf-8 text stamp
1 parentd0c5a01 commit355d908

File tree

3 files changed

+179
-3
lines changed

3 files changed

+179
-3
lines changed

‎include/blobstamper/stamp_text.h‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ class StampStringASCII: public StampBaseStr
4040
std::stringExtractStr(std::shared_ptr<Blob> blob)override;
4141
};
4242

43+
classStampStringUTF8:publicStampBaseStr
44+
{
45+
public:
46+
virtualintminSize()override {return3; }
47+
virtualintmaxSize()override {return -1; }
48+
std::stringExtractStr(std::shared_ptr<Blob> blob)override;
49+
};
50+
4351
template<classT>classStampText:publicGalleyVectorStrStampBase<T>
4452
{
4553
public:

‎src/stamp_text.cpp‎

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,139 @@ StampStringASCII::ExtractStr(std::shared_ptr<Blob> blob)
5454
return res;
5555
}
5656

57+
// FIXME: translate into English
58+
59+
/* Эта функция "нормализует" три байта до utf-32 символа.*/
60+
61+
/* В utf-32 для кодировки одного символа используется три байта, четвертый всегда не используется*/
62+
/* Первый и второй байт при этом используется полностью, а третий принимает значение от 0x00 до 0x10*/
63+
64+
/*
65+
* Нам надо нормолизовать первые три байта так, чтобы нормализованные значения были распределены равномерно
66+
* если нормализованные данные были распределены равномерно, или блико к тому. Проблема в том, как равномерно
67+
* распределить третий байт. Для значений 0x00..0x0F можно добиться равномерного распредеоения обнулив старшие
68+
* 4 бита. Тогда вероятность каждого из значений бует 1/16
69+
* Но у нас еще есть 0x10 который нельзя получить откидыванием бит, но который нам тоже нужен. При этом вероятонстью
70+
* равной или схожей с 0x00..0x0F.
71+
* Поэтому мы если старшие четыре бита принимают значение 0xF, то мы будем считать, что результат у нас 0x10. Вероятнсть этого 1/16
72+
* Во всех остальных случаях будем возвращать значение младших бит. За счет вышеуказанного кейса вероятность каждого значения станет 1/16-1/256
73+
* 1/256 -- это тот случай когда старшие четыре бита приняли значение 0xF
74+
* Будем считать это распредеделение вероятностей достаточно равномерным для наших задач
75+
*/
76+
77+
/*inline*/uint32_t
78+
ThreeBytesToUtf32UInt(char *buf)
79+
{
80+
uint32_t res =0;
81+
char * res_buf = (char *) &res;
82+
res_buf[3] =0;// Старший байт всегда ноль
83+
res_buf[1] = buf[1];
84+
res_buf[0] = buf[0];
85+
86+
if ( (buf[2] &0xF0) ==0xF0)// вероятность этого 1/16
87+
{
88+
res_buf[2] =0x10;
89+
}else
90+
{
91+
res_buf[2] = buf[2] &0x0F;// Значения от 0 до 0x0F, вероятность каждого из них 1/16 - 1/256 (с учетом предыдущей ветки if'а)
92+
}
93+
if ( (res_buf[2] ==0) && ((res_buf[1] &0xF8) ==0xD8))// 0x0000FyXX y=8..F, X=0..F
94+
{
95+
// Это суррогатные UTF-16 символы нулевого плейна которые в одиночку встречаться не должны. https://en.wikipedia.org/wiki/Universal_Character_Set_characters#Surrogates
96+
// Заменяем их на подчеркивание
97+
res_buf[1] =0;
98+
res_buf[0] ='_';
99+
}
100+
return res;
101+
}
102+
103+
size_t
104+
append_with_utf8(unsignedchar * buf,uint32_t c32)
105+
{
106+
// check if sum in ascii diapazone
107+
if(c32 <=0x7F)
108+
{
109+
buf[0] = c32 &0x7F;
110+
return1;
111+
}
112+
113+
// if contains 2 bytes
114+
if(c32 <=0x7FF)
115+
{
116+
// get 1st byte
117+
buf[0] =6 <<5;
118+
buf[0] += c32 >>6;
119+
// get 2nd byte
120+
buf[1] =2 <<6;
121+
buf[1] += c32 &0x3f;
122+
return2;
123+
}
124+
125+
// if contains 3 bytes
126+
if(c32 <=0xffff)
127+
{
128+
buf[0] =0xe <<4;
129+
buf[0] += c32 >>0xc;
130+
131+
buf[1] =2 <<6;
132+
buf[1] += (c32 >>6) &0x3f;
133+
134+
buf[2] =2 <<6;
135+
buf[2] += c32 &0x3f;
136+
return3;
137+
}
138+
139+
// if contains 4 bytes
140+
if(c32 <=0x10ffff)
141+
{
142+
buf[0] =0x1e <<3;
143+
buf[0] += (c32 >>0x12) &7;
144+
145+
buf[1] =2 <<6;
146+
buf[1] += (c32 >>0xc) &0x3f;
147+
148+
buf[2] =2 <<6;
149+
buf[2] += (c32 >>6) &0x3f;
150+
151+
buf[3] =2 <<6;
152+
buf[3] += c32 &0x3f;
153+
return4;
154+
155+
}else {
156+
/* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME*/
157+
printf("error in parsing utf32, maybe its not utf32?");
158+
return0;
159+
}
160+
}
161+
162+
void
163+
utf24_to_utf8(char * in,size_t in_size,char **out,size_t *out_size)
164+
{
165+
in_size = (in_size /3) *3;
166+
*out_size = (in_size /3) *4 +1;// +1 for final zero
167+
*out = (char *)malloc(*out_size);
168+
169+
unsignedchar * p = (unsignedchar*) *out;
170+
for(int i=0; i<in_size; i+=3)
171+
{
172+
uint32_t utf32 =ThreeBytesToUtf32UInt(in + i);
173+
p = p +append_with_utf8(p, utf32);
174+
}
175+
*p ='\0';// final zero
176+
}
177+
178+
std::string
179+
StampStringUTF8::ExtractStr(std::shared_ptr<Blob> blob)
180+
{
181+
std::vector<char> data = blob->Chop(minSize(),maxSize())->AsByteVector();
182+
183+
char * raw_res;
184+
size_t raw_res_size;
185+
186+
utf24_to_utf8(&data[0], data.size(), &raw_res, &raw_res_size);
187+
188+
std::string res = raw_res;
189+
free(raw_res);
190+
191+
return res;
192+
}

‎t/150-stamp_text.cpp‎

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ using namespace TAP;
3131
int
3232
main()
3333
{
34-
TEST_START(5);
34+
TEST_START(7);
3535
{/* 1..1*/
3636
char data[] ="папа\0мама\0бабушка\0дедушка\0братик\0сестричка";
3737
std::shared_ptr<Blob> blob = std::make_shared<Blob>(data, (sizeof data)-1);
@@ -51,28 +51,60 @@ main()
5151
}
5252

5353
{/* 3..3*/
54+
unsignedchar data[] = {
55+
0x41,0x00,0x00,0xB2,0x03,0x00,0x14,0x04,0x00,0x9C,0x4E,0x00,0xC4,0x30,0x00,0x36,0xF4,0x01,0x23,0x0E,0x00,0x0F,0x00,0x2C,
56+
0x03,0x26,0x00,0xA9,0xF4,0x01,0x19,0x4E,0x00,0x1E,0xF6,0x01,0x95,0x0D,0x00,0xA5,0x07,0x00,0x7D,0x0F,0x00,0xD0,0x05,0x00,
57+
0x13,0xF9,0x01,0xA9,0x03,0x00,0x66,0x5B,0x00,0x0A,0x0E,0x00,0xE3,0x53,0x00,0x30,0x2B,0x00,0xB8,0x30,0x01,0x7C,0xF4,0x01,
58+
0xA2,0xF3,0x01,0x35,0x0C,0x00,0x0D,0x4E,0x00,0xB0,0xF9,0x01,0xE6,0x0C,0x00,0x8E,0xF4,0x01,0xA9,0x06,0x00,0xC7,0xF4,0x01,
59+
0x5C,0x0B,0x00,0x4B,0x4E,0x00,0xD2,0x05,0x00,0x13,0xF9,0x01,0x28,0x0F,0x00,0xF4,0xF3,0x01,0x95,0x0B,0x00,0x80,0x0D,0x00,
60+
0x3E,0xF3,0x01,0x7B,
61+
};
62+
std::shared_ptr<Blob> blob = std::make_shared<Blob>((char *) data, (sizeof data)-1);
63+
StampStringUTF8 stamp_str_ascii;
64+
std::string s = stamp_str_ascii.ExtractStr(blob);
65+
is(s,"AβД亜ツ🐶ร󀀏☃💩丙😞ඕޥཽא🤓Ω学ช口⬰𓂸👼🎢వ不🦰೦💎ک📇ଡ଼之ג🤓༨🏴க඀🌾",
66+
"StampTextUTF8");
67+
}
68+
69+
{/* 4..4*/
5470
char data[] ="dad\0mam\0granddad\0grandmam\0brother\0sister";
5571
std::shared_ptr<Blob> blob = std::make_shared<Blob>(data, (sizeof data)-1);
5672
StampText<StampStringLatin1> stamp;
5773
std::string s = stamp.ExtractStr(blob);
5874
is(s,"d dad gra n dmam broth er siste","StampText<StampStringLatin1>");
5975
}
6076

61-
{/*4..4*/
77+
{/*5..5*/
6278
char data[] ="abcdef""abcdef""ABCDEF""012345";
6379
std::shared_ptr<Blob> blob = std::make_shared<Blob>(data, (sizeof data)-1);
6480
StampText<StampDictLCAlphaSmall> stamp;
6581
std::string s = stamp.ExtractStr(blob);
6682
is(s,"gleam godfather graffiti greened grouping gunshots gleam godfather graffiti greened grouping gunshots dismally dissented divested doorstep dread drunks convertors corpulent counterparts cranking crippled crusades","StampText<StampDictLCAlphaSmall>");
6783
}
6884

69-
{/*5..5*/
85+
{/*6..6*/
7086
char data[] ="Некоторый текст написанный русскими буквами в кодировке utf-8";
7187
std::shared_ptr<Blob> blob = std::make_shared<Blob>(data, (sizeof data)-1);
7288
StampText<StampStringASCII> stamp;
7389
std::string s = stamp.ExtractStr(blob);
7490
is(s,"P9 Q Q\x3Q\x1Q\x1P: P8 P<P 8 P 1Q\x3 P:P 2P0 P<P 8 P 2 P: P>P 4P8 Q P>P 2P :P5 ut f-8","StampText<StampStringASCII>");
7591
}
7692

93+
{/* 7..7*/
94+
unsignedchar data[] = {
95+
0x41,0x00,0x00,0xB2,0x03,0x00,0x14,0x04,0x00,0x9C,0x4E,0x00,0xC4,0x30,0x00,0x36,0xF4,0x01,0x23,0x0E,0x00,0x0F,0x00,0x2C,
96+
0x03,0x26,0x00,0xA9,0xF4,0x01,0x19,0x4E,0x00,0x1E,0xF6,0x01,0x95,0x0D,0x00,0xA5,0x07,0x00,0x7D,0x0F,0x00,0xD0,0x05,0x00,
97+
0x13,0xF9,0x01,0xA9,0x03,0x00,0x66,0x5B,0x00,0x0A,0x0E,0x00,0xE3,0x53,0x00,0x30,0x2B,0x00,0xB8,0x30,0x01,0x7C,0xF4,0x01,
98+
0xA2,0xF3,0x01,0x35,0x0C,0x00,0x0D,0x4E,0x00,0xB0,0xF9,0x01,0xE6,0x0C,0x00,0x8E,0xF4,0x01,0xA9,0x06,0x00,0xC7,0xF4,0x01,
99+
0x5C,0x0B,0x00,0x4B,0x4E,0x00,0xD2,0x05,0x00,0x13,0xF9,0x01,0x28,0x0F,0x00,0xF4,0xF3,0x01,0x95,0x0B,0x00,0x80,0x0D,0x00,
100+
0x3E,0xF3,0x01,0x7B,
101+
};
102+
std::shared_ptr<Blob> blob = std::make_shared<Blob>((char *)data, (sizeof data)-1);
103+
StampText<StampStringUTF8> stamp;
104+
std::string s = stamp.ExtractStr(blob);
105+
is(s,"񀀃󀀄񀁎񠀰𰇴󰀎𲰀򐀦򐇴󠁎񐇶񐀍󐀇𰀅򐇹񠀃򠁛𰀎S򀀫󀄰𠇴񐇳󐀌N񠇹󠀌򐇴񰀆󀇴򰀋𠁎𰀅򀇹􀀏񐇳 󠀍",
106+
"StampText<StampStringUTF8>");
107+
}
108+
77109
TEST_END;
78110
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp