Example usage for org.eclipse.jdt.core.compiler CharOperation indexOf

List of usage examples for org.eclipse.jdt.core.compiler CharOperation indexOf

Introduction

In this page you can find the example usage for org.eclipse.jdt.core.compiler CharOperation indexOf.

Prototype

public static final int indexOf(char toBeFound, char[] array, int start) 

Source Link

Document

Answers the first index in the array for which the corresponding character is equal to toBeFound starting the search at index start.

Usage

From source file:com.codenvy.ide.ext.java.server.internal.core.JavadocContents.java

License:Open Source License

private void computeTypeRange() throws JavaModelException {
    final int indexOfStartOfClassData = CharOperation.indexOf(JavadocConstants.START_OF_CLASS_DATA,
            this.content, false);
    if (indexOfStartOfClassData == -1) {
        this.typeDocRange = UNKNOWN_FORMAT;
        return;//  ww  w.j a v  a  2  s.  c  o  m
    }
    int indexOfNextSeparator = CharOperation.indexOf(JavadocConstants.SEPARATOR_START, this.content, false,
            indexOfStartOfClassData);
    if (indexOfNextSeparator == -1) {
        this.typeDocRange = UNKNOWN_FORMAT;
        return;
    }
    int indexOfNextSummary = CharOperation.indexOf(JavadocConstants.NESTED_CLASS_SUMMARY, this.content, false,
            indexOfNextSeparator);
    if (indexOfNextSummary == -1 && this.type.isEnum()) {
        // try to find enum constant summary start
        indexOfNextSummary = CharOperation.indexOf(JavadocConstants.ENUM_CONSTANT_SUMMARY, this.content, false,
                indexOfNextSeparator);
    }
    if (indexOfNextSummary == -1 && this.type.isAnnotation()) {
        // try to find required enum constant summary start
        indexOfNextSummary = CharOperation.indexOf(JavadocConstants.ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY,
                this.content, false, indexOfNextSeparator);
        if (indexOfNextSummary == -1) {
            // try to find optional enum constant summary start
            indexOfNextSummary = CharOperation.indexOf(JavadocConstants.ANNOTATION_TYPE_OPTIONAL_MEMBER_SUMMARY,
                    this.content, false, indexOfNextSeparator);
        }
    }
    if (indexOfNextSummary == -1) {
        // try to find field summary start
        indexOfNextSummary = CharOperation.indexOf(JavadocConstants.FIELD_SUMMARY, this.content, false,
                indexOfNextSeparator);
    }
    if (indexOfNextSummary == -1) {
        // try to find constructor summary start
        indexOfNextSummary = CharOperation.indexOf(JavadocConstants.CONSTRUCTOR_SUMMARY, this.content, false,
                indexOfNextSeparator);
    }
    if (indexOfNextSummary == -1) {
        // try to find method summary start
        indexOfNextSummary = CharOperation.indexOf(JavadocConstants.METHOD_SUMMARY, this.content, false,
                indexOfNextSeparator);
    }

    if (indexOfNextSummary == -1) {
        // we take the end of class data
        indexOfNextSummary = CharOperation.indexOf(JavadocConstants.END_OF_CLASS_DATA, this.content, false,
                indexOfNextSeparator);
    } else {
        // improve performance of computation of children ranges
        this.childrenStart = indexOfNextSummary + 1;
    }

    if (indexOfNextSummary == -1) {
        this.typeDocRange = UNKNOWN_FORMAT;
        return;
    }
    /*
     * Cut off the type hierarchy, see bug 119844.
     * We remove the contents between the start of class data and where
     * we guess the actual class comment starts.
     */
    int start = indexOfStartOfClassData + JavadocConstants.START_OF_CLASS_DATA_LENGTH;
    int indexOfFirstParagraph = CharOperation.indexOf(JavadocConstants.P.toCharArray(), this.content, false,
            start, indexOfNextSummary);
    int indexOfFirstDiv = CharOperation.indexOf(JavadocConstants.DIV_CLASS_BLOCK.toCharArray(), this.content,
            false, start, indexOfNextSummary);
    int afterHierarchy = indexOfNextSummary;
    if (indexOfFirstParagraph != -1 && indexOfFirstParagraph < afterHierarchy) {
        afterHierarchy = indexOfFirstParagraph;
    }
    if (indexOfFirstDiv != -1 && indexOfFirstDiv < afterHierarchy) {
        afterHierarchy = indexOfFirstDiv;
    }
    if (afterHierarchy != indexOfNextSummary) {
        start = afterHierarchy;
    }

    this.typeDocRange = new int[] { start, indexOfNextSummary };
}

From source file:com.codenvy.ide.ext.java.server.internal.core.search.indexing.BinaryIndexer.java

License:Open Source License

private char[] decodeFieldType(char[] signature) throws ClassFormatException {
    if (signature == null)
        return null;
    int arrayDim = 0;
    for (int i = 0, max = signature.length; i < max; i++) {
        switch (signature[i]) {
        case 'B':
            if (arrayDim > 0)
                return convertToArrayType(BYTE, arrayDim);
            return BYTE;

        case 'C':
            if (arrayDim > 0)
                return convertToArrayType(CHAR, arrayDim);
            return CHAR;

        case 'D':
            if (arrayDim > 0)
                return convertToArrayType(DOUBLE, arrayDim);
            return DOUBLE;

        case 'F':
            if (arrayDim > 0)
                return convertToArrayType(FLOAT, arrayDim);
            return FLOAT;

        case 'I':
            if (arrayDim > 0)
                return convertToArrayType(INT, arrayDim);
            return INT;

        case 'J':
            if (arrayDim > 0)
                return convertToArrayType(LONG, arrayDim);
            return LONG;

        case 'L':
            int indexOfSemiColon = CharOperation.indexOf(';', signature, i + 1);
            if (indexOfSemiColon == -1)
                throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
            if (arrayDim > 0) {
                return convertToArrayType(
                        replace('/', '.', CharOperation.subarray(signature, i + 1, indexOfSemiColon)),
                        arrayDim);//from   ww  w . j a  v a2s. c o  m
            }
            return replace('/', '.', CharOperation.subarray(signature, i + 1, indexOfSemiColon));

        case 'S':
            if (arrayDim > 0)
                return convertToArrayType(SHORT, arrayDim);
            return SHORT;

        case 'Z':
            if (arrayDim > 0)
                return convertToArrayType(BOOLEAN, arrayDim);
            return BOOLEAN;

        case 'V':
            return VOID;

        case '[':
            arrayDim++;
            break;

        default:
            throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
        }
    }
    return null;
}

From source file:com.codenvy.ide.ext.java.server.internal.core.search.indexing.BinaryIndexer.java

License:Open Source License

/**
 * For example:/*  w ww  .j a  v a2 s.c  om*/
 *   - int foo(String[]) is ([Ljava/lang/String;)I => java.lang.String[] in a char[][]
 *   - void foo(int) is (I)V ==> int
 */
private char[][] decodeParameterTypes(char[] signature, boolean firstIsSynthetic) throws ClassFormatException {
    if (signature == null)
        return null;
    int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
    if (indexOfClosingParen == 1) {
        // there is no parameter
        return null;
    }
    if (indexOfClosingParen == -1) {
        throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
    }
    char[][] parameterTypes = new char[3][];
    int parameterTypesCounter = 0;
    int arrayDim = 0;
    for (int i = 1; i < indexOfClosingParen; i++) {
        if (parameterTypesCounter == parameterTypes.length) {
            // resize
            System.arraycopy(parameterTypes, 0, (parameterTypes = new char[parameterTypesCounter * 2][]), 0,
                    parameterTypesCounter);
        }
        switch (signature[i]) {
        case 'B':
            parameterTypes[parameterTypesCounter++] = BYTE;
            if (arrayDim > 0)
                convertToArrayType(parameterTypes, parameterTypesCounter - 1, arrayDim);
            arrayDim = 0;
            break;

        case 'C':
            parameterTypes[parameterTypesCounter++] = CHAR;
            if (arrayDim > 0)
                convertToArrayType(parameterTypes, parameterTypesCounter - 1, arrayDim);
            arrayDim = 0;
            break;

        case 'D':
            parameterTypes[parameterTypesCounter++] = DOUBLE;
            if (arrayDim > 0)
                convertToArrayType(parameterTypes, parameterTypesCounter - 1, arrayDim);
            arrayDim = 0;
            break;

        case 'F':
            parameterTypes[parameterTypesCounter++] = FLOAT;
            if (arrayDim > 0)
                convertToArrayType(parameterTypes, parameterTypesCounter - 1, arrayDim);
            arrayDim = 0;
            break;

        case 'I':
            parameterTypes[parameterTypesCounter++] = INT;
            if (arrayDim > 0)
                convertToArrayType(parameterTypes, parameterTypesCounter - 1, arrayDim);
            arrayDim = 0;
            break;

        case 'J':
            parameterTypes[parameterTypesCounter++] = LONG;
            if (arrayDim > 0)
                convertToArrayType(parameterTypes, parameterTypesCounter - 1, arrayDim);
            arrayDim = 0;
            break;

        case 'L':
            int indexOfSemiColon = CharOperation.indexOf(';', signature, i + 1);
            if (indexOfSemiColon == -1)
                throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
            if (firstIsSynthetic && parameterTypesCounter == 0) {
                // skip first synthetic parameter
                firstIsSynthetic = false;
            } else {
                parameterTypes[parameterTypesCounter++] = replace('/', '.',
                        CharOperation.subarray(signature, i + 1, indexOfSemiColon));
                if (arrayDim > 0)
                    convertToArrayType(parameterTypes, parameterTypesCounter - 1, arrayDim);
            }
            i = indexOfSemiColon;
            arrayDim = 0;
            break;

        case 'S':
            parameterTypes[parameterTypesCounter++] = SHORT;
            if (arrayDim > 0)
                convertToArrayType(parameterTypes, parameterTypesCounter - 1, arrayDim);
            arrayDim = 0;
            break;

        case 'Z':
            parameterTypes[parameterTypesCounter++] = BOOLEAN;
            if (arrayDim > 0)
                convertToArrayType(parameterTypes, parameterTypesCounter - 1, arrayDim);
            arrayDim = 0;
            break;

        case '[':
            arrayDim++;
            break;

        default:
            throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
        }
    }
    if (parameterTypes.length != parameterTypesCounter) {
        System.arraycopy(parameterTypes, 0, parameterTypes = new char[parameterTypesCounter][], 0,
                parameterTypesCounter);
    }
    return parameterTypes;
}

From source file:com.codenvy.ide.ext.java.server.internal.core.search.indexing.BinaryIndexer.java

License:Open Source License

private char[] decodeReturnType(char[] signature) throws ClassFormatException {
    if (signature == null)
        return null;
    int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
    if (indexOfClosingParen == -1)
        throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
    int arrayDim = 0;
    for (int i = indexOfClosingParen + 1, max = signature.length; i < max; i++) {
        switch (signature[i]) {
        case 'B':
            if (arrayDim > 0)
                return convertToArrayType(BYTE, arrayDim);
            return BYTE;

        case 'C':
            if (arrayDim > 0)
                return convertToArrayType(CHAR, arrayDim);
            return CHAR;

        case 'D':
            if (arrayDim > 0)
                return convertToArrayType(DOUBLE, arrayDim);
            return DOUBLE;

        case 'F':
            if (arrayDim > 0)
                return convertToArrayType(FLOAT, arrayDim);
            return FLOAT;

        case 'I':
            if (arrayDim > 0)
                return convertToArrayType(INT, arrayDim);
            return INT;

        case 'J':
            if (arrayDim > 0)
                return convertToArrayType(LONG, arrayDim);
            return LONG;

        case 'L':
            int indexOfSemiColon = CharOperation.indexOf(';', signature, i + 1);
            if (indexOfSemiColon == -1)
                throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
            if (arrayDim > 0) {
                return convertToArrayType(
                        replace('/', '.', CharOperation.subarray(signature, i + 1, indexOfSemiColon)),
                        arrayDim);/*  ww  w  .  j a  va 2s  .c om*/
            }
            return replace('/', '.', CharOperation.subarray(signature, i + 1, indexOfSemiColon));

        case 'S':
            if (arrayDim > 0)
                return convertToArrayType(SHORT, arrayDim);
            return SHORT;

        case 'Z':
            if (arrayDim > 0)
                return convertToArrayType(BOOLEAN, arrayDim);
            return BOOLEAN;

        case 'V':
            return VOID;

        case '[':
            arrayDim++;
            break;

        default:
            throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
        }
    }
    return null;
}

From source file:com.codenvy.ide.ext.java.server.internal.core.search.indexing.BinaryIndexer.java

License:Open Source License

private int extractArgCount(char[] signature, char[] className) throws ClassFormatException {
    int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
    if (indexOfClosingParen == 1) {
        // there is no parameter
        return 0;
    }/*from www.j a v a 2  s.  c o  m*/
    if (indexOfClosingParen == -1) {
        throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
    }
    int parameterTypesCounter = 0;
    for (int i = 1; i < indexOfClosingParen; i++) {
        switch (signature[i]) {
        case 'B':
        case 'C':
        case 'D':
        case 'F':
        case 'I':
        case 'J':
        case 'S':
        case 'Z':
            parameterTypesCounter++;
            break;
        case 'L':
            int indexOfSemiColon = CharOperation.indexOf(';', signature, i + 1);
            if (indexOfSemiColon == -1)
                throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
            // verify if first parameter is synthetic
            if (className != null && parameterTypesCounter == 0) {
                char[] classSignature = Signature.createCharArrayTypeSignature(className, true);
                int length = indexOfSemiColon - i + 1;
                if (classSignature.length > (length + 1)) {
                    // synthetic means that parameter type has same signature than given class
                    for (int j = i, k = 0; j < indexOfSemiColon; j++, k++) {
                        if (!(signature[j] == classSignature[k]
                                || (signature[j] == '/' && classSignature[k] == '.'))) {
                            parameterTypesCounter++;
                            break;
                        }
                    }
                } else {
                    parameterTypesCounter++;
                }
                className = null; // do not verify following parameters
            } else {
                parameterTypesCounter++;
            }
            i = indexOfSemiColon;
            break;
        case '[':
            break;
        default:
            throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
        }
    }
    return parameterTypesCounter;
}

From source file:com.codenvy.ide.ext.java.server.internal.core.search.matching.ConstructorDeclarationPattern.java

License:Open Source License

public void decodeIndexKey(char[] key) {
    int last = key.length - 1;
    int slash = CharOperation.indexOf(SEPARATOR, key, 0);
    this.declaringSimpleName = CharOperation.subarray(key, 0, slash);

    int start = slash + 1;
    slash = CharOperation.indexOf(SEPARATOR, key, start);
    last = slash - 1;//from www  .j  a  v  a 2 s . c  o  m

    boolean isDefaultConstructor = key[last] == '#';
    if (isDefaultConstructor) {
        this.parameterCount = -1;
    } else {
        this.parameterCount = 0;
        int power = 1;
        for (int i = last; i >= start; i--) {
            if (i == last) {
                this.parameterCount = key[i] - '0';
            } else {
                power *= 10;
                this.parameterCount += power * (key[i] - '0');
            }
        }
    }

    slash = slash + 3;
    last = slash - 1;

    int typeModifiersWithExtraFlags = key[last - 1] + (key[last] << 16);
    this.declaringTypeModifiers = decodeModifers(typeModifiersWithExtraFlags);
    this.extraFlags = decodeExtraFlags(typeModifiersWithExtraFlags);

    // initialize optional fields
    this.declaringPackageName = null;
    this.modifiers = 0;
    this.signature = null;
    this.parameterTypes = null;
    this.parameterNames = null;

    boolean isMemberType = (this.extraFlags & ExtraFlags.IsMemberType) != 0;

    if (!isMemberType) {
        start = slash + 1;
        if (this.parameterCount == -1) {
            slash = key.length;
            last = slash - 1;
        } else {
            slash = CharOperation.indexOf(SEPARATOR, key, start);
        }
        last = slash - 1;

        this.declaringPackageName = CharOperation.subarray(key, start, slash);

        start = slash + 1;
        if (this.parameterCount == 0) {
            slash = slash + 3;
            last = slash - 1;

            this.modifiers = key[last - 1] + (key[last] << 16);
        } else if (this.parameterCount > 0) {
            slash = CharOperation.indexOf(SEPARATOR, key, start);
            last = slash - 1;

            boolean hasParameterStoredAsSignature = (this.extraFlags
                    & ExtraFlags.ParameterTypesStoredAsSignature) != 0;
            if (hasParameterStoredAsSignature) {
                this.signature = CharOperation.subarray(key, start, slash);
                CharOperation.replace(this.signature, '\\', SEPARATOR);
            } else {
                this.parameterTypes = CharOperation.splitOn(PARAMETER_SEPARATOR, key, start, slash);
            }
            start = slash + 1;
            slash = CharOperation.indexOf(SEPARATOR, key, start);
            last = slash - 1;

            if (slash != start) {
                this.parameterNames = CharOperation.splitOn(PARAMETER_SEPARATOR, key, start, slash);
            }

            slash = slash + 3;
            last = slash - 1;

            this.modifiers = key[last - 1] + (key[last] << 16);
        } else {
            this.modifiers = ClassFileConstants.AccPublic;
        }
    }

    removeInternalFlags(); // remove internal flags
}

From source file:com.codenvy.ide.ext.java.server.internal.core.search.matching.ConstructorPattern.java

License:Open Source License

public void decodeIndexKey(char[] key) {
    int last = key.length - 1;
    int slash = CharOperation.indexOf(SEPARATOR, key, 0);
    this.declaringSimpleName = CharOperation.subarray(key, 0, slash);

    int start = slash + 1;
    slash = CharOperation.indexOf(SEPARATOR, key, start);
    if (slash != -1) {
        last = slash - 1;//from  w  w w  .  jav  a  2 s .  c o m
    }

    boolean isDefaultConstructor = key[last] == '#';
    if (isDefaultConstructor) {
        this.parameterCount = -1;
    } else {
        this.parameterCount = 0;
        int power = 1;
        for (int i = last; i >= start; i--) {
            if (i == last) {
                this.parameterCount = key[i] - '0';
            } else {
                power *= 10;
                this.parameterCount += power * (key[i] - '0');
            }
        }
    }
}

From source file:com.codenvy.ide.ext.java.server.internal.core.search.matching.MatchLocator.java

License:Open Source License

public MethodBinding getMethodBinding(MethodPattern methodPattern) {
    MethodBinding methodBinding = getMethodBinding0(methodPattern);
    if (methodBinding != null)
        return methodBinding; // known to be valid.
    // special handling for methods of anonymous/local types. Since these cannot be looked up in the environment the usual way ...
    if (methodPattern.focus instanceof SourceMethod) {
        char[] typeName = PatternLocator.qualifiedPattern(methodPattern.declaringSimpleName,
                methodPattern.declaringQualification);
        if (CharOperation.indexOf(IIndexConstants.ONE_STAR, typeName, true) >= 0) { // See org.eclipse.jdt.core.search.SearchPattern.enclosingTypeNames(IType)
            IType type = methodPattern.declaringType;
            IType enclosingType = type.getDeclaringType();
            while (enclosingType != null) {
                type = enclosingType;/*from   w w w.j  av a2s .c  om*/
                enclosingType = type.getDeclaringType();
            }
            typeName = type.getFullyQualifiedName().toCharArray();
            TypeBinding declaringTypeBinding = getType(typeName, typeName);
            if (declaringTypeBinding instanceof SourceTypeBinding) {
                SourceTypeBinding sourceTypeBinding = ((SourceTypeBinding) declaringTypeBinding);
                ClassScope skope = sourceTypeBinding.scope;
                if (skope != null) {
                    CompilationUnitDeclaration unit = skope.referenceCompilationUnit();
                    if (unit != null) {
                        AbstractMethodDeclaration amd = new ASTNodeFinder(unit)
                                .findMethod((IMethod) methodPattern.focus);
                        if (amd != null && amd.binding != null && amd.binding.isValidBinding()) {
                            this.bindings.put(methodPattern, amd.binding);
                            return amd.binding;
                        }
                    }
                }
            }
        }
    }
    return null;
}

From source file:com.codenvy.ide.ext.java.server.internal.core.search.matching.QualifiedTypeDeclarationPattern.java

License:Open Source License

public void decodeIndexKey(char[] key) {
    int slash = CharOperation.indexOf(SEPARATOR, key, 0);
    this.simpleName = CharOperation.subarray(key, 0, slash);

    int start = ++slash;
    if (key[start] == SEPARATOR) {
        this.pkg = CharOperation.NO_CHAR;
    } else {//w  w  w.  j  ava  2s  . c o m
        slash = CharOperation.indexOf(SEPARATOR, key, start);
        this.pkg = internedPackageNames.add(CharOperation.subarray(key, start, slash));
    }
    this.qualification = this.pkg;

    // Continue key read by the end to decode modifiers
    int last = key.length - 1;
    this.secondary = key[last] == 'S';
    if (this.secondary) {
        last -= 2;
    }
    this.modifiers = key[last - 1] + (key[last] << 16);
    decodeModifiers();

    // Retrieve enclosing type names
    start = slash + 1;
    last -= 2; // position of ending slash
    if (start == last) {
        this.enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
    } else {
        int length = this.qualification.length;
        int size = last - start;
        System.arraycopy(this.qualification, 0, this.qualification = new char[length + 1 + size], 0, length);
        this.qualification[length] = '.';
        if (last == (start + 1) && key[start] == ZERO_CHAR) {
            this.enclosingTypeNames = ONE_ZERO_CHAR;
            this.qualification[length + 1] = ZERO_CHAR;
        } else {
            this.enclosingTypeNames = CharOperation.splitOn('.', key, start, last);
            System.arraycopy(key, start, this.qualification, length + 1, size);
        }
    }
}

From source file:com.codenvy.ide.ext.java.server.internal.core.search.matching.SuperTypeReferencePattern.java

License:Open Source License

public void decodeIndexKey(char[] key) {
    int slash = CharOperation.indexOf(SEPARATOR, key, 0);
    this.superSimpleName = CharOperation.subarray(key, 0, slash);

    // some values may not have been know when indexed so decode as null
    int start = slash + 1;
    slash = CharOperation.indexOf(SEPARATOR, key, start);
    this.superQualification = slash == start ? null : CharOperation.subarray(key, start, slash);

    slash = CharOperation.indexOf(SEPARATOR, key, start = slash + 1);
    this.simpleName = CharOperation.subarray(key, start, slash);

    start = ++slash;//  www  . j  a v a2  s .c  o m
    if (key[start] == SEPARATOR) {
        this.enclosingTypeName = null;
    } else {
        slash = CharOperation.indexOf(SEPARATOR, key, start);
        if (slash == (start + 1) && key[start] == ZERO_CHAR) {
            this.enclosingTypeName = ONE_ZERO;
        } else {
            char[] names = CharOperation.subarray(key, start, slash);
            this.enclosingTypeName = names;
        }
    }

    start = ++slash;
    if (key[start] == SEPARATOR) {
        this.typeParameterSignatures = null;
    } else {
        slash = CharOperation.indexOf(SEPARATOR, key, start);
        this.typeParameterSignatures = CharOperation.splitOn(',', key, start, slash);
    }

    start = ++slash;
    if (key[start] == SEPARATOR) {
        this.pkgName = null;
    } else {
        slash = CharOperation.indexOf(SEPARATOR, key, start);
        if (slash == (start + 1) && key[start] == ZERO_CHAR) {
            this.pkgName = this.superQualification;
        } else {
            char[] names = CharOperation.subarray(key, start, slash);
            this.pkgName = names;
        }
    }

    this.superClassOrInterface = key[slash + 1];
    this.classOrInterface = key[slash + 2];
    this.modifiers = key[slash + 3]; // implicit cast to int type
}