@@ -319,10 +319,11 @@ public long writeConverted(byte[] sourceBytes) throws IOException, FileDecoderEx
319319 len = sourceBytes .length ;
320320 start = 0 ;
321321 int bom = 0 ;
322+ boolean isGunZipType = isGunzipFileType (this .fileType );
322323
323- if (writeUtf8Bom ) {
324- this . write ( new byte []{( byte ) 0xEF , ( byte ) 0xBB , ( byte ) 0xBF }, 0 , 3 );
325- bom = 3 ;
324+ if (! isGunZipType ) {
325+ bom = addUtf8BomIfNeeded ( sourceBytes );
326+ sourceBytes = removeUtf8BomIfNeeded ( sourceBytes ) ;
326327 writeUtf8Bom = false ;
327328 }
328329
@@ -392,6 +393,11 @@ public long writeConverted(byte[] sourceBytes) throws IOException, FileDecoderEx
392393 case FST_XTEXT_GUNZIP :
393394 case FST_XUTF8_GUNZIP :
394395 sourceBytes = decompressSourceBytes (sourceBytes );
396+
397+ bom = addUtf8BomIfNeeded (sourceBytes );
398+ sourceBytes = removeUtf8BomIfNeeded (sourceBytes );
399+ writeUtf8Bom = false ;
400+
395401 if (this .lineEndStream != null ) {
396402 this .lineEndStream .write (sourceBytes , start , len );
397403 } else {
@@ -440,6 +446,68 @@ public long writeConverted(byte[] sourceBytes) throws IOException, FileDecoderEx
440446 return bytesWritten ;
441447 }
442448
449+ /**
450+ * Writes the UTF-8 BOM if writeUtf8Bom is true and sourceBytes does / doesn't already have one.
451+ *
452+ * @param sourceBytes the source byte array to check
453+ * @return the number of BOM bytes written (3 if BOM was added, 0 otherwise)
454+ * @throws IOException on error
455+ */
456+ private int addUtf8BomIfNeeded (byte [] sourceBytes ) throws IOException {
457+ // filesys.utf8bom = 1
458+ if (writeUtf8Bom && !hasUtf8Bom (sourceBytes )) {
459+ this .write (new byte []{(byte ) 0xEF , (byte ) 0xBB , (byte ) 0xBF }, 0 , 3 );
460+ return 3 ;
461+ }
462+ return 0 ;
463+ }
464+
465+ /**
466+ * Removes 1 UTF-8 BOM from sourceBytes if writeUtf8Bom is false and sourceBytes has one/many.
467+ * Also updates the len field to reflect the new length.
468+ *
469+ * @param sourceBytes the source byte array to process
470+ * @return the sourceBytes
471+ */
472+ private byte [] removeUtf8BomIfNeeded (byte [] sourceBytes ) {
473+ //filesys.utf8bom = 0
474+ if (!writeUtf8Bom && hasUtf8Bom (sourceBytes )) {
475+ byte [] newSourceBytes = new byte [sourceBytes .length - 3 ];
476+ System .arraycopy (sourceBytes , 3 , newSourceBytes , 0 , sourceBytes .length - 3 );
477+ len = newSourceBytes .length ;
478+ return newSourceBytes ;
479+ }
480+ return sourceBytes ;
481+ }
482+
483+ /**
484+ * Returns true when the first three bytes are BOM
485+ *
486+ * @param bytes
487+ * */
488+ private boolean hasUtf8Bom (byte [] bytes ) {
489+ return bytes != null && bytes .length >= 3
490+ && bytes [0 ] == (byte ) 0xEF
491+ && bytes [1 ] == (byte ) 0xBB
492+ && bytes [2 ] == (byte ) 0xBF ;
493+ }
494+
495+ /**
496+ * Returns true when the file type is GUNZIP type
497+ *
498+ * @param fileType
499+ * */
500+ private boolean isGunzipFileType (RpcPerforceFileType fileType ) {
501+ return fileType == RpcPerforceFileType .FST_TEXT_GUNZIP
502+ || fileType == RpcPerforceFileType .FST_UTF8_GUNZIP
503+ || fileType == RpcPerforceFileType .FST_XTEXT_GUNZIP
504+ || fileType == RpcPerforceFileType .FST_XUTF8_GUNZIP
505+ || fileType == RpcPerforceFileType .FST_UNICODE_GUNZIP
506+ || fileType == RpcPerforceFileType .FST_UTF16_GUNZIP
507+ || fileType == RpcPerforceFileType .FST_XUTF16_GUNZIP
508+ || fileType == RpcPerforceFileType .FST_XUNICODE_GUNZIP ;
509+ }
510+
443511 /**
444512 * Uncompress the source bytes and store them in "tempBufferToStoreCompressedBytes"
445513 *
0 commit comments