scala.reflect.internal.util.FreshNameCreator.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scala-reflect Show documentation
Show all versions of scala-reflect Show documentation
Reflection Library for the Scala Programming Language
/*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc.
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/
package scala.reflect.internal
package util
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicLong
import scala.reflect.NameTransformer
class FreshNameCreator(creatorPrefix: String = "") {
protected val counters = new ConcurrentHashMap[String, AtomicLong]()
/**
* Create a fresh name with the given prefix. It is guaranteed
* that the returned name has never been returned by a previous
* call to this function (provided the prefix does not end in a digit).
*/
def newName(prefix: String): String = {
val safePrefix = NameTransformer.encode(prefix)
val idx = allocateCounter(safePrefix).incrementAndGet()
assemble(safePrefix, idx)
}
/** Low level API for clients that want to perform multiple fresh names from the same prefix. */
def newNameFactory(prefix: String): NameFactory = {
val safePrefix = NameTransformer.encode(prefix)
val counter = allocateCounter(safePrefix)
new NameFactory(safePrefix, counter)
}
private def assemble(safePrefix: String, idx: Long) = {
val result = new java.lang.StringBuilder(creatorPrefix.length + safePrefix.length + decimalLength(idx))
result.append(creatorPrefix)
result.append(safePrefix)
result.append(idx)
creatorPrefix + safePrefix + idx
}
private def allocateCounter(safePrefix: String): AtomicLong = {
counters.computeIfAbsent(safePrefix, (s: String) => new AtomicLong(0))
}
final class NameFactory(safePrefix: String, counter: AtomicLong) {
def index(): Long = counter.incrementAndGet()
def newNameAtIndex(index: Long): String = assemble(safePrefix, index)
def newName(): String = newNameAtIndex(index())
}
def decimalLength(i: Long): Int = {
require(i >= 0, i)
var ceiling = 10
var numDigits = 1
val MaxValueLength = 19 // = Long.MaxValue.toString.length
while (numDigits <= MaxValueLength) {
if (i < ceiling) return numDigits
numDigits += 1
ceiling *= 10
}
MaxValueLength
}
}