1 | /* |
2 | * << Haru Free PDF Library >> -- hpdf_string.c |
3 | * |
4 | * URL: http://libharu.org |
5 | * |
6 | * Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp> |
7 | * Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org> |
8 | * |
9 | * Permission to use, copy, modify, distribute and sell this software |
10 | * and its documentation for any purpose is hereby granted without fee, |
11 | * provided that the above copyright notice appear in all copies and |
12 | * that both that copyright notice and this permission notice appear |
13 | * in supporting documentation. |
14 | * It is provided "as is" without express or implied warranty. |
15 | * |
16 | */ |
17 | |
18 | #include <string.h> |
19 | #include "hpdf_conf.h" |
20 | #include "hpdf_utils.h" |
21 | #include "hpdf_objects.h" |
22 | |
23 | static const HPDF_BYTE [] = { |
24 | 0xFE, 0xFF |
25 | }; |
26 | |
27 | |
28 | HPDF_String |
29 | HPDF_String_New (HPDF_MMgr mmgr, |
30 | const char *value, |
31 | HPDF_Encoder encoder) |
32 | { |
33 | HPDF_String obj; |
34 | |
35 | HPDF_PTRACE((" HPDF_String_New\n" )); |
36 | |
37 | obj = (HPDF_String)HPDF_GetMem (mmgr, sizeof(HPDF_String_Rec)); |
38 | if (obj) { |
39 | HPDF_MemSet (&obj->header, 0, sizeof(HPDF_Obj_Header)); |
40 | obj->header.obj_class = HPDF_OCLASS_STRING; |
41 | |
42 | obj->mmgr = mmgr; |
43 | obj->error = mmgr->error; |
44 | obj->encoder = encoder; |
45 | obj->value = NULL; |
46 | obj->len = 0; |
47 | |
48 | if (HPDF_String_SetValue (obj, value) != HPDF_OK) { |
49 | HPDF_FreeMem (obj->mmgr, obj); |
50 | return NULL; |
51 | } |
52 | } |
53 | |
54 | return obj; |
55 | } |
56 | |
57 | |
58 | HPDF_STATUS |
59 | HPDF_String_SetValue (HPDF_String obj, |
60 | const char *value) |
61 | { |
62 | HPDF_UINT len; |
63 | HPDF_STATUS ret = HPDF_OK; |
64 | |
65 | HPDF_PTRACE((" HPDF_String_SetValue\n" )); |
66 | |
67 | if (obj->value) { |
68 | HPDF_FreeMem (obj->mmgr, obj->value); |
69 | obj->len = 0; |
70 | } |
71 | |
72 | len = HPDF_StrLen(value, HPDF_LIMIT_MAX_STRING_LEN + 1); |
73 | |
74 | if (len > HPDF_LIMIT_MAX_STRING_LEN) |
75 | return HPDF_SetError (obj->error, HPDF_STRING_OUT_OF_RANGE, 0); |
76 | |
77 | obj->value = HPDF_GetMem (obj->mmgr, len + 1); |
78 | if (!obj->value) |
79 | return HPDF_Error_GetCode (obj->error); |
80 | |
81 | HPDF_StrCpy ((char *)obj->value, value, (char *)obj->value + len); |
82 | obj->len = len; |
83 | |
84 | return ret; |
85 | } |
86 | |
87 | void |
88 | HPDF_String_Free (HPDF_String obj) |
89 | { |
90 | if (!obj) |
91 | return; |
92 | |
93 | HPDF_PTRACE((" HPDF_String_Free\n" )); |
94 | |
95 | HPDF_FreeMem (obj->mmgr, obj->value); |
96 | HPDF_FreeMem (obj->mmgr, obj); |
97 | } |
98 | |
99 | |
100 | HPDF_STATUS |
101 | HPDF_String_Write (HPDF_String obj, |
102 | HPDF_Stream stream, |
103 | HPDF_Encrypt e) |
104 | { |
105 | HPDF_STATUS ret; |
106 | |
107 | /* |
108 | * When encoder is not NULL, text is changed to unicode using encoder, |
109 | * and it outputs by HPDF_write_binary method. |
110 | */ |
111 | |
112 | HPDF_PTRACE((" HPDF_String_Write\n" )); |
113 | |
114 | if (e) |
115 | HPDF_Encrypt_Reset (e); |
116 | |
117 | if (obj->encoder == NULL) { |
118 | if (e) { |
119 | if ((ret = HPDF_Stream_WriteChar (stream, '<')) != HPDF_OK) |
120 | return ret; |
121 | |
122 | if ((ret = HPDF_Stream_WriteBinary (stream, obj->value, |
123 | HPDF_StrLen ((char *)obj->value, -1), e)) != HPDF_OK) |
124 | return ret; |
125 | |
126 | return HPDF_Stream_WriteChar (stream, '>'); |
127 | } else { |
128 | return HPDF_Stream_WriteEscapeText (stream, (char *)obj->value); |
129 | } |
130 | } else { |
131 | HPDF_BYTE* src = obj->value; |
132 | HPDF_BYTE buf[HPDF_TEXT_DEFAULT_LEN * 2]; |
133 | HPDF_UINT tmp_len = 0; |
134 | HPDF_BYTE* pbuf = buf; |
135 | HPDF_INT32 len = obj->len; |
136 | HPDF_ParseText_Rec parse_state; |
137 | HPDF_UINT i; |
138 | |
139 | if ((ret = HPDF_Stream_WriteChar (stream, '<')) != HPDF_OK) |
140 | return ret; |
141 | |
142 | if ((ret = HPDF_Stream_WriteBinary (stream, UNICODE_HEADER, 2, e)) |
143 | != HPDF_OK) |
144 | return ret; |
145 | |
146 | HPDF_Encoder_SetParseText (obj->encoder, &parse_state, src, len); |
147 | |
148 | for (i = 0; (HPDF_INT32)i < len; i++) { |
149 | HPDF_BYTE b = src[i]; |
150 | HPDF_UNICODE tmp_unicode; |
151 | HPDF_ByteType btype = HPDF_Encoder_ByteType (obj->encoder, |
152 | &parse_state); |
153 | |
154 | if (tmp_len >= HPDF_TEXT_DEFAULT_LEN - 1) { |
155 | if ((ret = HPDF_Stream_WriteBinary (stream, buf, |
156 | tmp_len * 2, e)) != HPDF_OK) |
157 | return ret; |
158 | |
159 | tmp_len = 0; |
160 | pbuf = buf; |
161 | } |
162 | |
163 | if (btype != HPDF_BYTE_TYPE_TRIAL) { |
164 | if (btype == HPDF_BYTE_TYPE_LEAD) { |
165 | HPDF_BYTE b2 = src[i + 1]; |
166 | HPDF_UINT16 char_code = (HPDF_UINT16)((HPDF_UINT) b * 256 + b2); |
167 | |
168 | tmp_unicode = HPDF_Encoder_ToUnicode (obj->encoder, |
169 | char_code); |
170 | } else { |
171 | tmp_unicode = HPDF_Encoder_ToUnicode (obj->encoder, b); |
172 | } |
173 | |
174 | HPDF_UInt16Swap (&tmp_unicode); |
175 | HPDF_MemCpy (pbuf, (HPDF_BYTE*)&tmp_unicode, 2); |
176 | pbuf += 2; |
177 | tmp_len++; |
178 | } |
179 | } |
180 | |
181 | if (tmp_len > 0) { |
182 | if ((ret = HPDF_Stream_WriteBinary (stream, buf, tmp_len * 2, e)) |
183 | != HPDF_OK) |
184 | return ret; |
185 | } |
186 | |
187 | if ((ret = HPDF_Stream_WriteChar (stream, '>')) != HPDF_OK) |
188 | return ret; |
189 | } |
190 | |
191 | return HPDF_OK; |
192 | } |
193 | |
194 | |
195 | HPDF_INT32 |
196 | HPDF_String_Cmp (HPDF_String s1, |
197 | HPDF_String s2) |
198 | { |
199 | if (s1->len < s2->len) return -1; |
200 | if (s1->len > s2->len) return +1; |
201 | return memcmp(s1->value, s2->value, s1->len); |
202 | } |
203 | |