/* Checksums.java Purpose: Description: History: Thu Feb 5 11:40:21 2004, Created by tomyeh Copyright (C) 2004 Potix Corporation. All Rights Reserved. {{IS_RIGHT This program is distributed under LGPL Version 2.1 in the hope that it will be useful, but WITHOUT ANY WARRANTY. }}IS_RIGHT */ package org.zkoss.util; //NOTE: DO NOT modify the algorithm here because i3lb/HostInfo counts on it. //If you really have to modify, you have to reserve old codes and modify //HostInfo to call the old ones. /** * Checksum relevant utilities. * * @author tomyeh */ public class Checksums { /** The default skips. */ public static final String SKIPS = "DEOX"; /** Returns a readable string plus a checksum. * * @param skips specifies a string of characters that shall be skipped. * If null specified, "DEOX" is assumed. To skip nothing, specify "". * You can only specify upper-case letters: A-Z. And, it must be in * alphabetic order. */ public static final String toReadable(long val, String skips) { if (skips == null) skips = SKIPS; final int mod = 36 - skips.length(); if (val < 0) val = -val; int patch = (int)val; //used to patch for 4 digits if (patch < 0) patch = -patch; final StringBuffer sb = new StringBuffer(32); for (int digits = 0;;) { if (val == 0) { //no more digit if (digits == 4) { digits = 0; sb.append('-'); } while (digits++ != 3) { //align to 4 - 1 final int v = patch % mod; patch /= mod; sb.append(toReadableChar(v, skips)); } sb.append(getChecksum(sb, skips)); return sb.toString(); } if (digits++ == 4) { digits = 1; sb.append('-'); } final int v = (int)(val % mod); val /= mod; sb.append(toReadableChar(v, skips)); } } /** Returns the character of the specified val by skipping skips. * Note: the caller must ensure val is in the right range: * 0 - (36 - skips.length()). * * @param skips specifies a string of characters that shall be skipped. * If null specified, "DEOX" is assumed. To skip nothing, specify "". * You can only specify upper-case letters: A-Z. And, it must be in * alphabetic order. */ public static final char toReadableChar(int val, String skips) { if (val < 10) return (char)(val + '0'); if (skips == null) skips = SKIPS; char cc = (char)(val + ('A' - 10)); for (int j = 0, sklen = skips.length(); j < sklen; ++j) { final char sk = skips.charAt(j); if (cc < sk) break; ++cc; } return cc; } /** Returns the checksum character of the specified val. * <p>It use {@link #toReadableChar} to convert the checksum to a character. * <p>Note: it skips '-' and ' '. * * @param skips specifies a string of characters that shall be skipped. * If null specified, "DEOX" is assumed. To skip nothing, specify "". * You can only specify upper-case letters: A-Z. And, it must be in * alphabetic order. */ public static final char getChecksum(String val, String skips) { if (skips == null) skips = SKIPS; final int len = val.length(); int cksum = 0; for (int j = 0; j < len; ++j) { final char cc = val.charAt(j); if (cc != '-' && cc != ' ') cksum = cksum * 27 + cc; } if (cksum < 0) cksum = -cksum; return toReadableChar(cksum % (36 - skips.length()), skips); } /** Returns the checksum character of the specified val. * <p>It use {@link #toReadableChar} to convert the checksum to a character. * <p>Note: it skips '-' and ' '. * * @param skips specifies a string of characters that shall be skipped. * If null specified, "DEOX" is assumed. To skip nothing, specify "". * You can only specify upper-case letters: A-Z. And, it must be in * alphabetic order. */ public static final char getChecksum(StringBuffer val, String skips) { if (skips == null) skips = SKIPS; final int len = val.length(); int cksum = 0; for (int j = 0; j < len; ++j) { final char cc = val.charAt(j); if (cc != '-' && cc != ' ') cksum = cksum * 27 + cc; } if (cksum < 0) cksum = -cksum; return toReadableChar(cksum % (36 - skips.length()), skips); } }