Cache.java
package com.maybeitssquid.safeascii.internal;
import java.util.HashMap;
import java.util.Map;
import java.util.function.IntFunction;
/**
* A {@link Chainable} implementation that caches the results of character processing to improve
* performance.
*
* <p>This class maintains a cache of processed results to avoid re-computing values for the same
* inputs. It employs a hybrid storage strategy:
*
* <ul>
* <li>A direct array is used for fast lookup of ASCII characters.
* <li>A {@link HashMap} is used for all other Unicode codepoints.
* </ul>
*
* This structure ensures minimal overhead for common ASCII characters while supporting the full
* Unicode range.
*/
public class Cache extends Chainable {
private final CharSequence[] ascii = new CharSequence[ASCII];
private final Map<Integer, CharSequence> cache = new HashMap<>();
/**
* Creates a new Cache instance.
*
* @param delegate the next function in the chain to compute values for cache misses
*/
public Cache(final IntFunction<CharSequence> delegate) {
super(delegate);
}
/**
* Manually adds a value to the cache for a specific codepoint.
*
* @param codepoint the Unicode codepoint to cache
* @param value the processed string value to associate with the codepoint
*/
public void cache(final int codepoint, final CharSequence value) {
if (codepoint < ASCII) {
ascii[codepoint] = value;
} else {
cache.put(codepoint, value);
}
}
/**
* Retrieves a cached value for the given codepoint.
*
* @param codepoint the character to look up
* @return the cached {@link CharSequence} if available, otherwise {@code null}
*/
@Override
protected CharSequence process(final int codepoint) {
return codepoint < ASCII ? ascii[codepoint] : cache.get(codepoint);
}
/**
* Returns the processed string for a given codepoint, using the cache if available.
*
* <p>If the value is found in the cache, it is returned immediately. If not, the request is
* delegated to the upstream handler, and the result is cached for future use.
*
* @param value the codepoint to process
* @return the processed {@link CharSequence}
*/
@Override
public CharSequence apply(final int value) {
final CharSequence cached = process(value);
if (cached == null) {
final CharSequence result = delegate(value);
cache(value, result);
return result;
} else {
return cached;
}
}
}