@@ -1128,7 +1128,8 @@ PHPAPI char *php_stream_get_record(php_stream *stream, size_t maxlen, size_t *re
1128
1128
/* Writes a buffer directly to a stream, using multiple of the chunk size */
1129
1129
static size_t _php_stream_write_buffer (php_stream * stream , int buf_type , zstr buf , int buflen TSRMLS_DC )
1130
1130
{
1131
- size_t didwrite = 0 , towrite , justwrote ;
1131
+ size_t didwrite = 0 , towrite , justwrote , shouldwrite , buflen_orig = buflen ;
1132
+ zstr buf_orig = buf ;
1132
1133
char * freeme = NULL ;
1133
1134
1134
1135
/* if we have a seekable stream we need to ensure that data is written at the
@@ -1155,6 +1156,8 @@ static size_t _php_stream_write_buffer(php_stream *stream, int buf_type, zstr bu
1155
1156
}
1156
1157
}
1157
1158
1159
+ shouldwrite = buflen ;
1160
+
1158
1161
while (buflen > 0 ) {
1159
1162
towrite = buflen ;
1160
1163
if (towrite > stream -> chunk_size ) {
@@ -1179,6 +1182,36 @@ static size_t _php_stream_write_buffer(php_stream *stream, int buf_type, zstr bu
1179
1182
}
1180
1183
}
1181
1184
1185
+
1186
+ if (stream -> output_encoding ) {
1187
+ /* Map didwrite back to the original character count */
1188
+ if (didwrite == shouldwrite ) {
1189
+ /* Everything wrote okay, no need to count */
1190
+ didwrite = buflen_orig ;
1191
+ } else {
1192
+ UErrorCode status = U_ZERO_ERROR ;
1193
+ char * t = freeme ;
1194
+ UChar * p = buf_orig .u ;
1195
+
1196
+ switch (ucnv_getType (stream -> output_encoding )) {
1197
+ case UCNV_SBCS :
1198
+ case UCNV_LATIN_1 :
1199
+ case UCNV_US_ASCII :
1200
+ /* 1:1 character->byte mapping, didwrite really does mean the number of characters written */
1201
+ break ;
1202
+ default :
1203
+ /* Reconvert into junk buffer to see where conversion stops in source string */
1204
+ ucnv_resetFromUnicode (stream -> output_encoding );
1205
+ ucnv_fromUnicode (stream -> output_encoding , & t , t + didwrite , & p , p + buflen_orig , NULL , TRUE, & status );
1206
+ /* p stops at the first unconvertable UChar when t runs out of space */
1207
+ didwrite = p - buf_orig .u ;
1208
+ }
1209
+ }
1210
+ } else if (buf_type == IS_UNICODE ) {
1211
+ /* Was slopily converted */
1212
+ didwrite /= UBYTES (1 );
1213
+ }
1214
+
1182
1215
if (freeme ) {
1183
1216
efree (freeme );
1184
1217
}
@@ -1296,10 +1329,6 @@ PHPAPI size_t _php_stream_write_unicode(php_stream *stream, const UChar *buf, in
1296
1329
ret = _php_stream_write_buffer (stream , IS_UNICODE , (zstr )((UChar * )buf ), count TSRMLS_CC );
1297
1330
}
1298
1331
1299
- /* Return data points, not bytes */
1300
- if (ret > 0 ) {
1301
- ret >>= 1 ;
1302
- }
1303
1332
return ret ;
1304
1333
}
1305
1334
0 commit comments