001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.geometry.io.euclidean.threed.stl; 018 019import java.io.BufferedReader; 020import java.io.InputStream; 021import java.io.InputStreamReader; 022import java.io.PushbackInputStream; 023import java.nio.charset.Charset; 024import java.text.MessageFormat; 025import java.util.Arrays; 026 027import org.apache.commons.geometry.io.core.internal.GeometryIOUtils; 028import org.apache.commons.geometry.io.euclidean.threed.FacetDefinitionReader; 029 030/** Utility class with factory methods for constructing {@link FacetDefinitionReader} 031 * instances for STL content. 032 */ 033public final class StlFacetDefinitionReaders { 034 035 /** Utility class; no instantiation. */ 036 private StlFacetDefinitionReaders() { } 037 038 /** Construct a {@link FacetDefinitionReader} for reading STL content from the 039 * given input. The format of the input is checked to determine if it is a binary 040 * or text file and an appropriate reader is returned. 041 * @param in input to read from 042 * @param charset charset to use when checking the input for text content; 043 * if null, the input is assumed to use the UTF-8 charset 044 * @return facet definition reader 045 * @throws IllegalStateException if a parsing error occurs 046 * @throws java.io.UncheckedIOException if an I/O error occurs 047 */ 048 public static FacetDefinitionReader create(final InputStream in, final Charset charset) { 049 final Charset inputCharset = charset != null ? 050 charset : 051 StlConstants.DEFAULT_CHARSET; 052 053 final byte[] testBytes = StlConstants.SOLID_START_KEYWORD.getBytes(inputCharset); 054 final byte[] actualBytes = new byte[testBytes.length]; 055 056 final int read = GeometryIOUtils.applyAsIntUnchecked(in::read, actualBytes); 057 if (read < actualBytes.length) { 058 throw GeometryIOUtils.parseError(MessageFormat.format( 059 "Cannot determine STL format: attempted to read {0} bytes but found only {1} available", 060 actualBytes.length, read)); 061 } 062 063 // "unread" the test bytes so that the created readers can start from the 064 // beginning of the content 065 final PushbackInputStream pushbackInput = new PushbackInputStream(in, actualBytes.length); 066 GeometryIOUtils.acceptUnchecked(pushbackInput::unread, actualBytes); 067 068 if (Arrays.equals(testBytes, actualBytes)) { 069 // this is a text file 070 return new TextStlFacetDefinitionReader( 071 new BufferedReader(new InputStreamReader(pushbackInput, inputCharset))); 072 } else { 073 // this is a binary file 074 return new BinaryStlFacetDefinitionReader(pushbackInput); 075 } 076 } 077}