package com.intellij.flex.uiDesigner.io; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.LightVirtualFile; import com.intellij.util.Consumer; import com.intellij.util.Processor; import com.intellij.util.text.CharArrayCharSequence; import com.intellij.util.text.CharSequenceReader; import com.intellij.util.xml.NanoXmlUtil; import net.n3.nanoxml.IXMLBuilder; import java.awt.*; import java.awt.color.ColorSpace; import java.awt.image.*; import java.io.*; import java.net.Socket; import java.net.URL; import java.net.URLConnection; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; public final class IOUtil { private static final Logger LOG = Logger.getInstance(IOUtil.class.getName()); private static final ComponentColorModel COLOR_MODER = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[]{8, 8, 8}, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); private IOUtil() { } public static BufferedImage readImage(File file, Processor<DataInputStream> inProcessor) throws IOException { DataInputStream in = new DataInputStream(new FileInputStream(file)); try { if (inProcessor.process(in)) { int w = in.readUnsignedShort(); int h = in.readUnsignedShort(); return createImage(w, h, FileUtil.loadBytes(in, w * h * 3)); } else { return null; } } finally { in.close(); } } public static BufferedImage readARGBImage(DataInputStream in) throws IOException { final int w = in.readUnsignedShort(); if (w == 0) { return null; } final int h = in.readUnsignedShort(); int l = w * h * 4; final byte[] data = FileUtil.loadBytes(in, l); for (int i = 0, j = 0; i < l; i += 4) { data[j++] = data[i + 3]; byte r = data[i + 1]; data[j++] = data[i + 2]; data[j++] = r; } return createImage(w, h, data); } private static BufferedImage createImage(int w, int h, byte[] bgr) { return new BufferedImage(COLOR_MODER, Raster.createInterleavedRaster(new DataBufferByte(bgr, w * h * 3), w, h, w * 3, 3, new int[]{2, 1, 0}, null), false, null); } public static void saveImage(BufferedImage image, File file, Consumer<DataOutputStream> outConsumer) throws IOException { DataOutputStream out = new DataOutputStream(new FileOutputStream(file)); try { outConsumer.consume(out); out.writeShort(image.getWidth()); out.writeShort(image.getHeight()); out.write(((DataBufferByte)image.getRaster().getDataBuffer()).getData()); } finally { out.close(); } } public static byte[] getResourceBytes(String name) throws IOException { InputStream classDefinition = IOUtil.class.getClassLoader().getResourceAsStream(name); try { return FileUtil.adaptiveLoadBytes(classDefinition); } finally { classDefinition.close(); } } public static void saveStream(URL source, File target) throws IOException { final URLConnection sourceConnection = source.openConnection(); final long sourceLastModified = sourceConnection.getLastModified(); if (target.lastModified() == sourceLastModified) { // target file is already up to date return; } //noinspection ResultOfMethodCallIgnored target.getParentFile().mkdirs(); final FileOutputStream outputStream = new FileOutputStream(target); try { FileUtil.copy(sourceConnection.getInputStream(), outputStream); } finally { outputStream.close(); } //noinspection ResultOfMethodCallIgnored target.setLastModified(sourceLastModified); } public static int uint29SizeOf(int counter) { return counter < 0x80 ? 1 : 2; } public static byte[] getBytes(ByteProvider... byteProviders) { int size = 0; for (ByteProvider byteProvider : byteProviders) { size += byteProvider.size(); } byte[] bytes = new byte[size]; int offset = 0; for (ByteProvider byteProvider : byteProviders) { offset = byteProvider.writeTo(bytes, offset); } return bytes; } public static void writeInt(final int v, final byte[] bytes, int offset) { bytes[offset++] = (byte)((v >>> 24) & 0xff); bytes[offset++] = (byte)((v >>> 16) & 0xff); bytes[offset++] = (byte)((v >>> 8) & 0xff); bytes[offset] = (byte)(v & 0xff); } public static void writeShort(final int v, final byte[] bytes, int offset) { bytes[offset++] = (byte)((v >>> 8) & 0xFF); bytes[offset] = (byte)(v & 0xFF); } public static void close(Socket socket) { if (socket != null) { try { socket.close(); } catch (IOException e) { LOG.error(e); } } } public static void writeAmfIntOrDouble(final PrimitiveAmfOutputStream out, final CharSequence value, final boolean isNegative, final boolean isInt) { if (isInt || StringUtil.indexOf(value, '.') == -1) { out.writeAmfInt(parseInt(value, 0, isNegative, 10)); } else { final double v = Double.parseDouble(value.toString()); out.writeAmfDouble(isNegative ? -v : v); } } /** * Javolution - Java(TM) Solution for Real-Time and Embedded Systems * Copyright (C) 2006 - Javolution (http://javolution.org/) * All rights reserved. * * Permission to use, copy, modify, and distribute this software is * freely granted, provided that this notice is preserved. */ public static int parseInt(final CharSequence value, final int start, final boolean isNegative, final int radix) { final int end = value.length(); int result = 0; // Accumulates negatively (avoid MIN_VALUE overflow). int i = start; for (; i < end; i++) { char c = value.charAt(i); int digit = (c <= '9') ? c - '0' : ((c <= 'Z') && (c >= 'A')) ? c - 'A' + 10 : ((c <= 'z') && (c >= 'a')) ? c - 'a' + 10 : -1; if ((digit >= 0) && (digit < radix)) { int newResult = result * radix - digit; if (newResult > result) { throw new NumberFormatException("Overflow parsing " + value.subSequence(start, end)); } result = newResult; } else { break; } } // Requires one valid digit character and checks for opposite overflow. if ((result == 0) && ((end == 0) || (value.charAt(i - 1) != '0'))) { throw new NumberFormatException("Invalid integer representation for " + value.subSequence(start, end)); } if ((result == Integer.MIN_VALUE) && !isNegative) { throw new NumberFormatException("Overflow parsing " + value.subSequence(start, end)); } return isNegative ? result : -result; } public static long parseLong(final CharSequence value, final int start, final boolean isNegative, final int radix) { final int end = value.length(); long result = 0; // Accumulates negatively (avoid MIN_VALUE overflow). int i = start; for (; i < end; i++) { char c = value.charAt(i); int digit = (c <= '9') ? c - '0' : ((c <= 'Z') && (c >= 'A')) ? c - 'A' + 10 : ((c <= 'z') && (c >= 'a')) ? c - 'a' + 10 : -1; if (digit >= 0 && digit < radix) { long newResult = result * radix - digit; if (newResult > result) { throw new NumberFormatException("Overflow parsing " + value.subSequence(start, end)); } result = newResult; } else { break; } } // Requires one valid digit character and checks for opposite overflow. if (result == 0 && (end == 0 || (value.charAt(i - 1) != '0'))) { throw new NumberFormatException("Invalid integer representation for " + value.subSequence(start, end)); } if ((result == Long.MIN_VALUE) && !isNegative) { throw new NumberFormatException("Overflow parsing " + value.subSequence(start, end)); } return isNegative ? result : -result; } private static Object getCharSequenceOrReader(VirtualFile file, boolean returnReader) throws IOException { if (file instanceof LightVirtualFile) { final CharSequence content = ((LightVirtualFile)file).getContent(); return returnReader ? new CharSequenceReader(content) : content; } return getCharSequenceOrReader(file.getInputStream(), (int)file.getLength(), file.getCharset(), returnReader); } private static Object getCharSequenceOrReader(InputStream inputStream, int length, Charset charset, boolean returnReader) throws IOException { final InputStreamReader reader = new InputStreamReader(inputStream, charset); try { char[] chars = new char[length]; int count = 0; while (count < chars.length) { int n = reader.read(chars, count, chars.length - count); if (n <= 0) { break; } count += n; } return returnReader ? new CharArrayReader(chars, 0, count) : new CharArrayCharSequence(chars, 0, count); } finally { reader.close(); } } public static CharSequence getCharSequence(File file) throws IOException { return (CharSequence)getCharSequenceOrReader(new FileInputStream(file), (int)file.length(), StandardCharsets.UTF_8, false); } public static CharArrayReader getCharArrayReader(InputStream inputStream, int length) throws IOException { return (CharArrayReader)getCharSequenceOrReader(inputStream, length, StandardCharsets.UTF_8, true); } public static void parseXml(VirtualFile file, IXMLBuilder builder) throws IOException { NanoXmlUtil.parse((Reader)getCharSequenceOrReader(file, true), builder); } }