/*
 * Copyright 2020-2021 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.lettuce.core.internal;

import java.util.Collection;
import java.util.Iterator;

/**
 * Helper for {@link String} checks. This class is part of the internal API and may change without further notice.
 *
 * @author Mark Paluch
 * @since 3.0
 */
public class LettuceStrings {

    /**
     * Utility constructor.
     */
    private LettuceStrings() {

    }

    /**
     * Checks if a CharSequence is empty ("") or null.
     *
     * @param cs the char sequence
     * @return true if empty
     */
    public static boolean isEmpty(final CharSequence cs) {
        return cs == null || cs.length() == 0;
    }

    /**
     * Checks if a CharSequence is not empty ("") and not null.
     *
     * @param cs the char sequence
     * @return true if not empty
     *
     */
    public static boolean isNotEmpty(final CharSequence cs) {
        return !isEmpty(cs);
    }

    /**
     * Convert {@code double} to {@link String}. If {@code n} is infinite, returns positive/negative infinity {@code +inf} and
     * {@code -inf}.
     *
     * @param n the double.
     * @return string representation of {@code n}
     */
    public static String string(double n) {
        if (Double.isInfinite(n)) {
            return (n > 0) ? "+inf" : "-inf";
        }
        return Double.toString(n);
    }

    /**
     * Convert {@link String} to {@code double}. If {@code s} is {@literal +inf}/{@literal -inf}, returns positive/negative
     * infinity. If {@code s} is {@literal +nan}/{@literal -nan}, returns NaN.
     *
     * @param s string representation of the number
     * @return the {@code double} value.
     * @since 4.3.3
     */
    public static double toDouble(String s) {

        if ("+inf".equals(s) || "inf".equals(s)) {
            return Double.POSITIVE_INFINITY;
        }

        if ("-inf".equals(s)) {
            return Double.NEGATIVE_INFINITY;
        }

        if ("-nan".equals(s) || "nan".equals(s) || "+nan".equals(s)) {
            return Double.NaN;
        }

        return Double.parseDouble(s);
    }

    /**
     * Convert a {@code String} array into a delimited {@code String} (e.g. CSV).
     * <p>
     * Useful for {@code toString()} implementations.
     *
     * @param arr the array to display
     * @param delim the delimiter to use (typically a ",")
     * @return the delimited {@code String}
     */
    public static String arrayToDelimitedString(Object[] arr, String delim) {

        if ((arr == null || arr.length == 0)) {
            return "";
        }

        if (arr.length == 1) {
            return "" + arr[0];
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            if (i > 0) {
                sb.append(delim);
            }
            sb.append(arr[i]);
        }
        return sb.toString();
    }

    /**
     * Convert a {@link Collection} to a delimited {@code String} (e.g. CSV).
     * <p>
     * Useful for {@code toString()} implementations.
     *
     * @param coll the {@code Collection} to convert
     * @param delim the delimiter to use (typically a ",")
     * @param prefix the {@code String} to start each element with
     * @param suffix the {@code String} to end each element with
     * @return the delimited {@code String}
     */
    public static String collectionToDelimitedString(Collection<?> coll, String delim, String prefix, String suffix) {

        if (coll == null || coll.isEmpty()) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        Iterator<?> it = coll.iterator();
        while (it.hasNext()) {
            sb.append(prefix).append(it.next()).append(suffix);
            if (it.hasNext()) {
                sb.append(delim);
            }
        }
        return sb.toString();
    }

}

@@ -1007,36 +1007,30 @@
 Checks if a 
-CharSequence
+String
  is empty (%22
@@ -1026,21 +1026,16 @@
 is empty
- (%22%22)
  or null
@@ -1117,68 +1117,475 @@
    *
-/%0A    public static boolean isEmpty(final CharSequence cs) %7B
+ @since 6.0.3%0A     * @see String#isEmpty()%0A     */%0A    public static boolean isEmpty(String cs) %7B%0A        return cs == null %7C%7C cs.isEmpty();%0A    %7D%0A%0A    /**%0A     * Checks if a CharSequence has a length of 0 or null.%0A     *%0A     * @param cs the char sequence%0A     * @return true if empty%0A     * @see CharSequence#length()%0A     */%0A    public static boolean isEmpty(CharSequence cs) %7B%0A        if (cs instanceof String) %7B%0A            return isEmpty((String) cs);%0A        %7D
 %0A   
@@ -1666,23 +1666,106 @@
 f a 
-CharS
+String is not empty and not null.%0A     *%0A     * @param cs the char s
 equence
+%0A     * @return true
  i
-s
+f
  not
@@ -1774,18 +1774,221 @@
 mpty
- (%22%22)
+%0A     * @since 6.0.3%0A     * @see String#isEmpty()%0A     */%0A    public static boolean isNotEmpty(String cs) %7B%0A        return !isEmpty(cs);%0A    %7D%0A%0A    /**%0A     * Checks if a CharSequence has a non-zero length
  and 
+is 
 not 
@@ -2070,24 +2070,51 @@
 empty%0A     *
+ @see CharSequence#length()
 %0A     */%0A   
@@ -2151,14 +2151,8 @@
 pty(
-final 
 Char

Introduce LettuceStrings.isEmpty(String) overload with optimized isEmpty checking #1609