/*
* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* This source file is part of the Cangjie project, licensed under Apache-2.0
* with Runtime Library Exception.
*
* See https://cangjie-lang.cn/pages/LICENSE for license information.
*/
package stdx.string_intern
import std.sync.AtomicOptionReference
/**
* Define an open interface for string-intern. Users should not use this interface, but directly use the {String#intern} method
*/
public interface Internable {
/**
* Returns a canonical representation for the string object.
*
* @param str new string object
* @return string object in strings pool
*/
static func intern(str: String): String
/**
* Returns a canonical representation for the string object.
*
* @param array new array object
* @return string object in strings pool
*/
static func intern(array: Array<Byte>): String
/**
* Config string intern pool
*
* @param capacity dynamic string pool capacity
* @param strMaxLength max lenght of string in dynamic string pool
*/
static func configInternPool(capacity!: Int64, strMaxLength!: Int64): Unit
}
class InternStringPoolHolder {
static let poolRef = AtomicOptionReference<InternStringPool>()
static func intern(value: String): String {
if (value.size == 0) {
return String.empty
}
match (poolRef.load()) {
case Some(pool) => return pool.intern(value)
case None => return value
}
}
static func intern(value: Array<Byte>): String {
if (value.size == 0) {
return String.empty
}
match (poolRef.load()) {
case Some(pool) => return pool.intern(value)
case None =>
let raw = unsafe {
String.withRawData(value)
}
return raw
}
}
static func config(capacity: Int64, strMaxLength: Int64): Unit {
poolRef.compareAndSwap(None, InternStringPool(capacity, strMaxLength))
}
}
extend String <: Internable {
/**
* Returns a canonical representation for the string object.
*
* @param str new string object
* @return string object in strings pool
*/
public static func intern(str: String): String {
return InternStringPoolHolder.intern(str)
}
/**
* Returns a canonical representation for the string object.
*
* @param array new array object
* @return string object which is same as array in strings pool
*/
public static func intern(array: Array<Byte>): String {
return InternStringPoolHolder.intern(array)
}
/**
* Config string intern pool
*
* @param capacity dynamic string pool capacity
* @param strMaxLength max lenght of string in dynamic string pool
*/
public static func configInternPool(capacity!: Int64 = 8192, strMaxLength!: Int64 = 512): Unit {
if (capacity <= 0) {
throw IllegalArgumentException("capacity should be positive: " + capacity.toString())
}
if (strMaxLength <= 0) {
throw IllegalArgumentException("strMaxLength should be positive: " + strMaxLength.toString())
}
InternStringPoolHolder.config(capacity, strMaxLength)
}
}