/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.fs.exfat; import java.io.IOException; /** * TODO: Add support for compressed format: * http://www.ntfs.com/exfat-upcase-table.htm * * @author Matthias Treydte <waldheinz at gmail.com> */ public final class UpcaseTable { public static UpcaseTable read(ExFatSuperBlock sb, long startCluster, long size, long checksum) throws IOException { Cluster.checkValid(startCluster); /* validate size */ if ((size == 0) || (size > (0xffff * 2)) || (size % 2) != 0) { throw new IOException("bad upcase table size " + size); } final UpcaseTable result = new UpcaseTable(sb, sb.clusterToOffset(startCluster), size); /* verify checksum */ final long actualCs = result.checkSum(); if (checksum != actualCs) { final StringBuilder msg = new StringBuilder(); msg.append("checksum mismatch (expected 0x"); msg.append(Long.toHexString(checksum)); msg.append(", got 0x"); msg.append(Long.toHexString(actualCs)); msg.append(")"); throw new IOException(msg.toString()); } return result; } private final ExFatSuperBlock sb; /** * Size in bytes. */ private final long size; /** * Number of chars. */ private final long chars; /** * Offset to the first byte of the table, relative to byte 0 on the * device. */ private final long offset; private final DeviceAccess da; private UpcaseTable(ExFatSuperBlock sb, long offset, long size) { this.sb = sb; this.da = sb.getDeviceAccess(); this.size = size; this.chars = size / 2; this.offset = offset; } /** * Gets the offset to the upcase table. * * @return the offset. */ public long getOffset() { return offset; } /** * Gets the size of the upcase table. * * @return the size. */ public long getSize() { return size; } public long checkSum() throws IOException { long sum = 0; for (int i = 0; i < size; i++) { sum = ((sum << 31) | (sum >> 1)) + da.getUint8(offset + i); sum &= 0xffffffffl; } return sum; } public char toUpperCase(char c) throws IOException { if (c > this.chars) { return c; } else { return da.getChar(offset + (c * 2)); } } public String toUpperCase(String s) throws IOException { final StringBuilder result = new StringBuilder(s.length()); for (char c : s.toCharArray()) { result.append(toUpperCase(c)); } return result.toString(); } public long getCharCount() { return this.chars; } }