All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.editor.ext.StringCache Maven / Gradle / Ivy

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.editor.ext;

import org.netbeans.editor.StringMap;

/**
* Cache holding the most commonly used strings.
* The unused strings are discarded when they reach the end of chain.
*
* @author Miloslav Metelka
* @version 1.00
*/

public class StringCache {

    private static final int DEFAULT_MAX_SIZE = 300;

    private static final int DEFAULT_INITIAL_CAPACITY = 701;

    int maxSize;

    int size;

    StringMap strMap;

    /** First chain member */
    private Entry chain;

    /** Last chain member */
    private Entry endChain;

    /** Last entry that was made free */
    private Entry freeEntry;

    public int statQueries; // count of queries
    public int statHits; // count of cache hits

    public StringCache() {
        this(DEFAULT_MAX_SIZE, DEFAULT_INITIAL_CAPACITY);
    }

    public StringCache(int maxSize) {
        this(maxSize, 2 * maxSize);
    }

    public StringCache(int maxSize, int initialMapCapacity) {
        this.maxSize = maxSize;
        strMap = new StringMap(initialMapCapacity);
    }

    private void toStart(Entry e) {
        if (e != chain) {
            // chain removal
            Entry ep = e.prev; // ep surely not null
            Entry en = e.next;
            if (en != null) {
                en.prev = ep;
            } else { // last chain member
                endChain = ep;
            }
            ep.next = en;

            // insert to chain start
            if (chain != null) {
                e.next = chain;
                chain.prev = e;
            }
            chain = e;
        }
    }

    public String getString(char[] chars, int offset, int len) {
        statQueries++;
        Object o = strMap.get(chars, offset, len);
        String ret;
        if (o instanceof Entry) {
            Entry e = (Entry)o;
            toStart(e);
            statHits++;
            ret = e.str;
        } else if (o instanceof String) {
            statHits++;
            ret = (String)o;
        } else { // string not found in cache
            ret = new String(chars, offset, len);
            storeString(ret);
        }
        return ret;
    }

    /** Remove string that can be in the cache */
    private void removeString(String s) {
        Object o = strMap.remove(s);
        if (o instanceof Entry) {
            Entry e = (Entry)o;
            Entry ep = e.prev;
            Entry en = e.next;

            if (e == chain) {
                chain = en;
                if (e == endChain) {
                    endChain = null;
                }
            } else { // not begining of chain
                if (en != null) {
                    en.prev = ep;
                } else {
                    endChain = ep;
                }
            }

            freeEntry = e; // free - can be reused for addition
            size--;
        }
        /* In other cases the removed object was either
        * the string which should be fine here
        * or it was null.
        */
    }

    /** Store string that's not yet in the cache */
    private void storeString(String s) {
        Entry e;
        if (size >= maxSize) {
            // take last one and move to begining and replace value
            e = endChain;
            toStart(e);
            strMap.remove(e.str);
            e.str = s;
        } else { // count of entries less than max
            if (freeEntry != null) {
                e = freeEntry;
                freeEntry = null;
                e.str = s;
                e.next = chain;
            } else {
                e = new Entry(s, chain);
            }

            if (chain != null) {
                chain.prev = e;
            } else { // nothing inserted yet
                endChain = e;
            }
            chain = e;
            size++;
        }
        strMap.put(s, e);
    }

    /** Put a string into cache that will survive there
    * so that it will be never removed.
    */
    public void putSurviveString(String s) {
        removeString(s);
        strMap.put(s, s);
    }

    static class Entry {

        Entry(String str, Entry next) { // prev always null
            this.str = str;
            this.next = next;
        }

        String str;

        Entry next;

        Entry prev;

    }

    public String toString() {
        String ret = "size=" + size + ", maxSize=" + maxSize // NOI18N
                     + ", statHits=" + statHits + ", statQueries=" + statQueries; // NOI18N
        if (statQueries > 0) {
            ret += ", hit ratio=" + (statHits * 100 / statQueries) + "%"; // NOI18N
        }
        return ret;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy