/*


    ========== licence begin GPL
    Copyright (C) 2002-2003 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end


*/

package com.sap.dbtech.util;

import java.util.*;
/**
 *
 *
 */
public abstract class StringUtil {
    // constants
    private final static byte blank_C = 32;
    public final static char[] hexDigits_C = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};


    public static byte[] bytes_iso8859_1(String str)
    {
        char[] ca=str.toCharArray();
        int strlen;
        byte[] r=new byte[strlen=ca.length];
        for(int i=0; i<strlen; ++i) {
            char c=ca[i];
            if(c <= 255) {
                r[i]=(byte)c;
            } else {
                r[i]=63; // ?
            }
        }
        return r;
    }

    public static boolean isIso8859_1(String str)
    {
        int strlen = str.length();
        for(int i=0; i<strlen; ++i) {
            char c=str.charAt(i);
            if(c > 255) {
                return false;
            }
        }
        return true;
    }
    
    public static byte[] bytes_ascii7bit(String str) {
		char[] ca=str.toCharArray();
		int strlen;
		byte[] r=new byte[strlen=ca.length];
		for(int i=0; i<strlen; ++i) {
			char c=ca[i];
			if(c <= 127) {
				r[i]=(byte)c;
			} else {
				r[i]=63; // ?
			}
		}
		return r;
    	
    }

    /**
     *
     * @return java.lang.String[]
     * @param line java.lang.String
     */
    public static String[] breakCommandLine (
        String source)
    {
        Vector tmpvec = new Vector (10);
        int pos = 0;
        int endPos = source.length ();
        String newval;
        String [] result;
        char [] chars = source.toCharArray ();
        char quoteChar = 0;
        final int inWS_C = 0;
        final int inWord_C = 1;
        int state = inWS_C;
        boolean inQuote = false;
        char current;
        int wordLen = 0;
        char [] word = new char [chars.length];

        while (pos < endPos) {
            current = chars [pos];
            if (Character.isWhitespace (current)) {
                switch (state) {
                    case inWS_C:
                        // simply skip
                        break;
                    case inWord_C:
                        if (inQuote) {
                            // inside word
                            word [wordLen] = current;
                            ++wordLen;
                        }
                        else {
                            // at end of word
                            newval = String.copyValueOf (word, 0, wordLen);
                            tmpvec.addElement (newval);
                            wordLen = 0;
                        }
                        break;
                }
            }
            else {
                switch (current) {
                    case '\'':
                    case '"':
                        if (inQuote) {
                            if (quoteChar == current) {
                                inQuote = false;
                            }
                            else {
                                word [wordLen] = current;
                                ++wordLen;
                            }
                        }
                        else {
                            inQuote = true;
                            quoteChar = current;
                            state = inWord_C;
                        }
                        break;
                    case '\\':
                        ++pos;
                        current = chars [pos];
                        word [wordLen] = current;
                        ++wordLen;
                        state = inWord_C;
                        break;
                    default:
                        word [wordLen] = current;
                        ++wordLen;
                        state = inWord_C;
                        break;
                }
            }
            ++pos;
        }
        if (state == inWord_C) {
            newval = String.copyValueOf (word, 0, wordLen);
            tmpvec.addElement (newval);
        }
        result = new String [tmpvec.size ()];
        for (int i = 0; i < result.length; ++i) {
            result [i] = (String) tmpvec.elementAt (i);
        }
        return result;
    }
    /**
     *
     * @return java.lang.String
     * @param format java.lang.String
     * @param objects java.lang.Object[]
     */
    public static void fprintf (
        java.io.PrintStream stream,
        String format,
        Object [] objects)
    throws com.sap.dbtech.util.printf.PrintfException
    {
        stream.print (sprintf (format, objects));
    }
    /**
     *
     * @return java.lang.String
     * @param format java.lang.String
     * @param objects java.lang.Object[]
     */
    public static void fprintf (
        java.io.PrintWriter stream,
        String format,
        Object [] objects)
    throws com.sap.dbtech.util.printf.PrintfException
    {
        stream.print (sprintf (format, objects));
    }
    /**
     *
     * @return java.lang.String
     * @param format java.lang.String
     * @param objects java.lang.Object[]
     */
    public static void fprintfs (
        java.io.PrintStream stream,
        String format,
        Object [] objects)
    {
        stream.print (sprintfs (format, objects));
    }
    /**
     *
     * @return java.lang.String
     * @param format java.lang.String
     * @param objects java.lang.Object[]
     */
    public static void fprintfs (
        java.io.PrintWriter stream,
        String format,
        Object [] objects)
    {
        stream.print (sprintfs (format, objects));
    }
    /**
     *
     * @return java.lang.String
     * @param buf byte[]
     * @param offs int
     * @param len int
     */
    public static String hexDump (
        byte [] buf)
    {
        return hexDump (buf, 0, buf.length, 0);
    }
    /**
     *
     * @return java.lang.String
     * @param buf byte[]
     * @param offs int
     * @param len int
     */
    public static String hexDump (
        byte [] buf,
        int from,
        int to)
    {
        return hexDump (buf, from, to, 0);
    }
    /**
     *
     * @return java.lang.String
     * @param buf byte[]
     * @param offs int
     * @param len int
     */
    public static String hexDump (
        byte [] buf,
        int from,
        int to,
        int logicalPos)
    {
        StringBuffer result = new StringBuffer ();
        final int chunkSize_C = 16;
        final int posExtent_C = 4;
        final int hexStart_C = posExtent_C + 3;
        final int clearStart_C = hexStart_C + 52;
        final int lineLen_C = clearStart_C + 19;
        StringBuffer line = new StringBuffer (lineLen_C);
        int virtualFrom;
        int nextBreak;
        int i;

        for (i = 0; i < posExtent_C; ++ i) {
            line.append ('0');
        }
        for (i = posExtent_C; i < lineLen_C; ++ i) {
            line.append (' ');
        }
        line.append ('\n');
        while (from < to) {
            virtualFrom = from - (from % chunkSize_C);
            nextBreak = virtualFrom + chunkSize_C;
            if (nextBreak > to) {
                nextBreak = to;
            }
            // put pos number
            int bufPos = from + logicalPos;
            int digitPos = posExtent_C - 1;
            while (bufPos > 0) {
                line.setCharAt (digitPos, hexDigits_C [bufPos % 16]);
                bufPos /= 16;
                --digitPos;
            }
            // put character data
            line.setCharAt (clearStart_C - 1, ' ');
            line.setCharAt (clearStart_C - 1 + from - virtualFrom, '\'');
            for (i = from - virtualFrom; i < nextBreak - virtualFrom; ++ i) {
                byte b = buf [i + virtualFrom];
                char ch;
                if (b >= 0)
                    ch = (char) b;
                else
                    ch = (char) (256 + b);
                // write hex
                line.setCharAt (hexStart_C + (i * 3) + 1, hexDigits_C [ch / 16]);
                line.setCharAt (hexStart_C + (i * 3) + 2, hexDigits_C [ch % 16]);
                // write plain
                if (ch < 32)
                    ch = '.';
                line.setCharAt (clearStart_C + i, ch);
            }
            line.setCharAt (clearStart_C + nextBreak - virtualFrom, '\'');
            // clear rest of line
            for (i = to - virtualFrom; i < chunkSize_C; ++ i) {
                // clear hex
                line.setCharAt (hexStart_C + (i * 3) + 1, ' ');
                line.setCharAt (hexStart_C + (i * 3) + 2, ' ');
                // clear plain
                //outstream.println ("clearing at " + String.valueOf (i)
                //  + "  " + String.valueOf  (clearStart_C + i + 1));
                line.setCharAt (clearStart_C + i + 1, ' ');
            }
            result.append (line.toString ());
            from = nextBreak;
        }
        return result.toString ();
    }
    /**
     *
     * @return java.lang.String
     * @param values Vector
     * @param delimiter java.lang.String
     */
    public static String join (
        Enumeration enume)
    {
        return join (enume, " ");
    }
    /**
     *
     * @return java.lang.String
     * @param values Vector
     * @param delimiter java.lang.String
     */
    public static String join (
        Enumeration enume,
        String delimiter)
    {
        StringBuffer buf = new StringBuffer ();

        if (enume.hasMoreElements ()) {
            buf.append (enume.nextElement ());
        }
        while (enume.hasMoreElements ()) {
            buf.append (delimiter);
            buf.append (enume.nextElement ());
        }
        return buf.toString ();
    }
    /**
     *
     * @return java.lang.String
     * @param len int
     * @param ch char
     */
    public static String padLeft (
        String str,
        int len)
    {
        return padLeft (str, len, ' ');
    }
    /**
     *
     * @return java.lang.String
     * @param len int
     * @param ch char
     */
    public static String padLeft (
        String str,
        int len,
        char ch)
    {
        int strlen = str.length ();
        StringBuffer buf;

        if (len <= strlen) {
            return str;
        }
        buf = new StringBuffer (len);
        for (int i = strlen; i < len; ++i) {
            buf.append (ch);
        }
        buf.append (str);
        return buf.toString ();
    }
    /**
     *
     * @return java.lang.String
     * @param len int
     * @param ch char
     */
    public static String padRight (
        String str,
        int len)
    {
        return padRight (str, len, ' ');
    }
    /**
     *
     * @return java.lang.String
     * @param len int
     * @param ch char
     */
    public static String padRight (
        String str,
        int len,
        char ch)
    {
        int strlen = str.length ();
        StringBuffer buf;

        if (len <= strlen) {
            return str;
        }
        buf = new StringBuffer (len);
        buf.append (str);
        for (int i = strlen; i < len; ++i) {
            buf.append (ch);
        }
        return buf.toString ();
    }
    /**
     *
     * @return java.lang.String
     * @param s java.lang.String
     * @param count int
     */
    public static String repeat (
        String s,
        int count)
    {
        StringBuffer buf = new StringBuffer (count * s.length ());
        for (int i = 0; i < count; ++i) {
            buf.append (s);
        }
        return buf.toString ();
    }
    /**
     *
     * @return java.lang.String
     * @param source java.lang.String
     * @param oldPart java.lang.String
     * @param newPart java.lang.String
     */
    public static String replace (
        String source,
        String oldPart,
        String newPart)
    {
        int startPos = 0;
        int foundPos = 0;

        foundPos = source.indexOf(oldPart, startPos);
        if (foundPos == -1) {
            return source;
        }
        StringBuffer result = new StringBuffer ();
        int oldLen = oldPart.length ();
        while (foundPos != -1) {
            result.append(source.substring (startPos, foundPos));
            result.append (newPart);
            startPos = foundPos + oldLen;
            foundPos = source.indexOf(oldPart, startPos);
        }
        result.append (source.substring (startPos, source.length()));
        return result.toString ();
    }
    /**
     *
     * @return java.lang.String[]
     * @param source java.lang.String
     * @param delimiter java.lang.String
     */
    public static String [] split (
        String source,
        String delimiter)
    {
        Vector tmpvec = new Vector (10);
        int delimLen = delimiter.length ();
        int lastPos = 0;
        int pos = 0;
        String newval;
        String [] result;

        pos = source.indexOf (delimiter, lastPos);
        while (pos != -1) {
            newval = source.substring (lastPos, pos);
            tmpvec.addElement (newval);
            lastPos = pos + delimLen;
            pos = source.indexOf (delimiter, lastPos);
        }
        newval = source.substring (lastPos);
        tmpvec.addElement (newval);
        result = new String [tmpvec.size ()];
        for (int i = 0; i < result.length; ++i) {
            result [i] = (String) tmpvec.elementAt (i);
        }
        return result;
    }
    /**
     *
     * @return java.lang.String[]
     * @param source java.lang.String
     * @param delimiter java.lang.String
     */
    public static String [] splitOnSpace (
        String source)
    {
        Vector tmpvec = new Vector (10);
        int lastPos = 0;
        int pos = 0;
        int endPos = source.length ();
        String newval;
        String [] result;
        char [] chars = source.toCharArray ();

        while (pos < endPos) {
            boolean inWhiteSpace = true;
            while ((lastPos < endPos) && inWhiteSpace) {
                char current = chars [lastPos];
                switch (current) {
                    case ' ':
                    case '\t':
                    case '\n':
                    case '\r':
                        ++lastPos;
                        break;
                    default:
                        inWhiteSpace = false;
                        break;
                }
            }
            pos = lastPos;
            if (pos < endPos) {
                inWhiteSpace = false;
                while ((pos < endPos) && !inWhiteSpace) {
                    char current = chars [lastPos];
                    switch (current) {
                        case ' ':
                        case '\t':
                        case '\n':
                        case '\r':
                            inWhiteSpace = true;
                            break;
                        default:
                            ++pos;
                            break;
                    }
                }
                newval = String.copyValueOf (chars, lastPos, pos - lastPos);
                tmpvec.addElement (newval);
                lastPos = pos;
            }
        }
        result = new String [tmpvec.size ()];
        for (int i = 0; i < result.length; ++i) {
            result [i] = (String) tmpvec.elementAt (i);
        }
        return result;
    }
    /**
     *
     * @return java.lang.String[]
     * @param source java.lang.String
     * @param delimiter java.lang.String
     */
    public static String [] splitOnSpaceIsWhiteSpace (
        String source)
    {
        Vector tmpvec = new Vector (10);
        int lastPos = 0;
        int pos = 0;
        int endPos = source.length ();
        String newval;
        String [] result;
        char [] chars = source.toCharArray ();

        while (pos < endPos) {
            while ((lastPos < endPos) && Character.isWhitespace(chars [lastPos])) {
                ++lastPos;
            }
            pos = lastPos;
            if (pos < endPos) {
                while ((pos < endPos) && !Character.isWhitespace(chars [pos])) {
                    ++pos;
                }
                newval = String.copyValueOf (chars, lastPos, pos - lastPos);
                tmpvec.addElement (newval);
                lastPos = pos;
            }
        }
        result = new String [tmpvec.size ()];
        for (int i = 0; i < result.length; ++i) {
            result [i] = (String) tmpvec.elementAt (i);
        }
        return result;
    }
    /**
     *
     * @return java.lang.String[]
     * @param source java.lang.String
     * @param delimiter java.lang.String
     */
    public static String [] splitOnSpaceRaw (
        String source)
    {
        Vector tmpvec = new Vector (10);
        int lastPos = 0;
        int pos = 0;
        int endPos = source.length ();
        String newval;
        String [] result;
        char [] chars = source.toCharArray ();

        while (pos < endPos) {
            boolean inWhiteSpace = true;
            while ((lastPos < endPos) && inWhiteSpace) {
                char current = chars [lastPos];
                switch (current) {
                    case ' ':
                    case '\t':
                    case '\n':
                    case '\r':
                        ++lastPos;
                        break;
                    default:
                        inWhiteSpace = false;
                        break;
                }
            }
            pos = lastPos;
            if (pos < endPos) {
                inWhiteSpace = false;
                while ((pos < endPos) && !inWhiteSpace) {
                    char current = chars [lastPos];
                    switch (current) {
                        case ' ':
                        case '\t':
                        case '\n':
                        case '\r':
                            inWhiteSpace = true;
                            break;
                        default:
                            ++pos;
                            break;
                    }
                }
                newval = String.copyValueOf (chars, lastPos, pos - lastPos);
                tmpvec.addElement (newval);
                lastPos = pos;
            }
        }
        result = new String [tmpvec.size ()];
        for (int i = 0; i < result.length; ++i) {
            result [i] = (String) tmpvec.elementAt (i);
        }
        return result;
    }
    /**
     *
     * @return java.lang.String[]
     * @param source java.lang.String
     * @param delimiter java.lang.String
     */
    public static String [] splitOnSpaceStringTokenizer (
        String source)
    {
        String [] result;
        Vector tmpvec = new Vector (10);
        StringTokenizer tokenizer = new StringTokenizer (source);

        while (tokenizer.hasMoreTokens()) {
            tmpvec.addElement(tokenizer.nextToken());
        }
        result = new String [tmpvec.size ()];
        for (int i = 0; i < result.length; ++i) {
            result [i] = (String) tmpvec.elementAt (i);
        }
        return result;
    }
    /**
     *
     * @return java.lang.String
     * @param format java.lang.String
     * @param objects java.lang.Object[]
     */
    public static String sprintf (
        String format,
        Object [] objects)
    throws com.sap.dbtech.util.printf.PrintfException
    {
        com.sap.dbtech.util.printf.PrintfFormat formatter;
        String result;

        formatter = new com.sap.dbtech.util.printf.PrintfFormat (format);
        result = formatter.format (objects);
        return result;
    }
    /**
     *
     * @return java.lang.String
     * @param format java.lang.String
     * @param objects java.lang.Object[]
     */
    public static String sprintfs (
        String format,
        Object [] objects)
    {
        try {
            return sprintf (format, objects);
        }
        catch (com.sap.dbtech.util.printf.PrintfException exc) {
            return "<PrintfError: " + exc.getMessage () + " >";
        }
    }
    /**
     *
     * @return java.lang.String
     * @param str java.lang.String
     * @param from int
     * @param to int
     */
    public static String substring (
        String str,
        int from,
        int to)
    {
        int strlen = str.length ();
        String result;

        if (from < 0) {
            from = strlen - from;
        }
        if (from < 0) {
            from = 0;
        }
        if (to < 0) {
            to = strlen - to;
        }
        if (to > strlen) {
            to = strlen;
        }
        if ((from > strlen) || (to < 0)) {
            result = "";
        }
        else {
            result = str.substring (from, to);
        }
        return result;
    }

    
    /**
     * Trims blanks <code>ASCII 0x20</code> from the right side of a string.
     * @param fullString the string that shall be trimmed.
     * @return A string where trailing blanks are removed.
     */
    public static String trimLeft (String fullString)
    {
        int l=fullString.length();
        for(int i=l-1; i>=0; --i) {
            if(fullString.charAt(i)!=0x20) {
                if(i==l-1) { 
                    return fullString;
                } else {
                    // Create a new String instance because 
                    // 'substring()' uses the same underlying buffer
                    // and so wastes a lot of memory possibly.
                    // return fullString.substring(0, i+1);
                    return new String(fullString.substring(0, i+1));
                }
            }
        }
        return "";
    }
    

    public static String formatMilliSeconds(java.sql.Timestamp d)
    {
        long fractional=d.getNanos() / 10000;
        String s=Long.toString(fractional);
        return "00000".substring(0, 5 - s.length()) + s;
    }
}
