diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java index d3c7b188e17..470ea5f1943 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ITypeMarshalBuffer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2009, 2012 Wind River Systems, Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * Markus Schorn - initial API and implementation * Thomas Corbat + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser; @@ -69,9 +70,18 @@ public interface ITypeMarshalBuffer { ISerializableEvaluation unmarshalEvaluation() throws CoreException; ICPPTemplateArgument unmarshalTemplateArgument() throws CoreException; int getByte() throws CoreException; - int getShort() throws CoreException; - int getInt() throws CoreException; - long getLong() throws CoreException; + int getFixedInt() throws CoreException; + + /** + * Reads a 32-bit integer stored in the variable length base-128 encoding. + */ + public int getInt() throws CoreException; + + /** + * Reads a 64-bit integer stored in the variable length base-128 encoding. + */ + public long getLong() throws CoreException; + char[] getCharArray() throws CoreException; void marshalType(IType type) throws CoreException; @@ -80,8 +90,53 @@ public interface ITypeMarshalBuffer { void marshalEvaluation(ISerializableEvaluation eval, boolean includeValue) throws CoreException; void marshalTemplateArgument(ICPPTemplateArgument arg) throws CoreException; void putByte(byte data); - void putShort(short data); - void putInt(int data); - void putLong(long data); + void putFixedInt(int data); + + /** + * Writes a 32-bit integer in the variable length base-128 encoding. Each byte, except the last + * byte, has the most significant bit set – this indicates that there are further bytes to come. + * The lower 7 bits of each byte are used to store the two-complement representation of + * the number in groups of 7 bits, least significant group first. + * + *
Here is number of bytes depending on the encoded value: + *
+ * Value Number of bytes + * [0,127] 1 + * [128,16383] 2 + * [16384,2097151] 3 + * [2097152,268435455] 4 + * [268435456,Integer.MAX_VALUE] 5 + * negative 5 + *+ * + * @param value the value to write + */ + public void putInt(int value); + + /** + * Writes a 64-bit integer in the variable length base-128 encoding. Each byte, except the last + * byte, has the most significant bit set – this indicates that there are further bytes to come. + * The lower 7 bits of each byte are used to store the two-complement representation of + * the number in groups of 7 bits, least significant group first. + * + *
Here is number of bytes depending on the encoded value: + *
+ * Value Number of bytes + * [0,127] 1 + * [128,16383] 2 + * [16384,2097151] 3 + * [2097152,268435455] 4 + * [268435456,2^35-1] 5 + * [2^35,2^42-1] 6 + * [2^42,2^49-1] 7 + * [2^49,2^56-1] 8 + * [2^56,2^63-1] 9 + * negative 10 + *+ * + * @param value the value to write + */ + public void putLong(long value); + void putCharArray(char[] data); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemFunctionType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemFunctionType.java index 5c11ff95c55..fdeddcf8d21 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemFunctionType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemFunctionType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2010, 2012 Wind River Systems, Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * Markus Schorn - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser; @@ -28,11 +29,11 @@ public class ProblemFunctionType extends ProblemType implements ICPPFunctionType @Override public void marshal(ITypeMarshalBuffer buffer) throws CoreException { buffer.putByte((byte) (ITypeMarshalBuffer.PROBLEM_TYPE | ITypeMarshalBuffer.FLAG1)); - buffer.putShort((short) getID()); + buffer.putInt(getID()); } public static IType unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException { - return new ProblemFunctionType(buffer.getShort()); + return new ProblemFunctionType(buffer.getInt()); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemType.java index 92d6ac9ee0b..8c6852c2935 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2010, 2012 Wind River Systems, Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * Markus Schorn - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser; @@ -56,13 +57,13 @@ public class ProblemType implements IProblemType, ISerializableType { @Override public void marshal(ITypeMarshalBuffer buffer) throws CoreException { buffer.putByte(ITypeMarshalBuffer.PROBLEM_TYPE); - buffer.putShort((short) getID()); + buffer.putInt(getID()); } public static IType unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException { if ((firstByte & ITypeMarshalBuffer.FLAG1) != 0) return ProblemFunctionType.unmarshal(firstByte, buffer); - return new ProblemType(buffer.getShort()); + return new ProblemType(buffer.getInt()); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java index 40e95a7be0b..4e5a941bc05 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java @@ -154,12 +154,12 @@ public class Value implements IValue { Long num= numericalValue(); if (num != null) { long lv= num; - if (lv >= Integer.MIN_VALUE && lv <= Integer.MAX_VALUE) { + if (lv >= 0) { buf.putByte((byte) (ITypeMarshalBuffer.VALUE | ITypeMarshalBuffer.FLAG2)); - buf.putInt((int) lv); + buf.putLong(lv); } else { buf.putByte((byte) (ITypeMarshalBuffer.VALUE | ITypeMarshalBuffer.FLAG3)); - buf.putLong(lv); + buf.putLong(-lv); } } else if (fFixedValue != null) { buf.putByte((byte) (ITypeMarshalBuffer.VALUE | ITypeMarshalBuffer.FLAG4)); @@ -177,18 +177,13 @@ public class Value implements IValue { return null; if ((firstByte & ITypeMarshalBuffer.FLAG1) != 0) return Value.UNKNOWN; - if ((firstByte & ITypeMarshalBuffer.FLAG2) != 0) { - int val= buf.getInt(); - return Value.create(val); - } - if ((firstByte & ITypeMarshalBuffer.FLAG3) != 0) { - long val= buf.getLong(); - return Value.create(val); - } - if ((firstByte & ITypeMarshalBuffer.FLAG4) != 0) { - char[] fixedValue = buf.getCharArray(); - return new Value(fixedValue, null); - } + if ((firstByte & ITypeMarshalBuffer.FLAG2) != 0) + return Value.create(buf.getLong()); + if ((firstByte & ITypeMarshalBuffer.FLAG3) != 0) + return Value.create(-buf.getLong()); + if ((firstByte & ITypeMarshalBuffer.FLAG4) != 0) + return new Value(buf.getCharArray(), null); + ISerializableEvaluation eval= buf.unmarshalEvaluation(); if (eval instanceof ICPPEvaluation) return new Value(null, (ICPPEvaluation) eval); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CArrayType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CArrayType.java index d9869e70ddc..42a3be333bf 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CArrayType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CArrayType.java @@ -1,12 +1,13 @@ /******************************************************************************* - * Copyright (c) 2004, 2010 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html + * Copyright (c) 2004, 2012 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html * - * Contributors: - * Devin Steffler (IBM Corporation) - initial API and implementation + * Contributors: + * Devin Steffler (IBM Corporation) - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; @@ -161,7 +162,7 @@ public class CArrayType implements ICArrayType, ITypeContainer, ISerializableTyp public void marshal(ITypeMarshalBuffer buffer) throws CoreException { int firstByte= ITypeMarshalBuffer.ARRAY_TYPE; int flags= 0; - short nval= -1; + long nval= -1; IValue val= null; if (isConst()) flags |= 0x01; @@ -178,9 +179,8 @@ public class CArrayType implements ICArrayType, ITypeContainer, ISerializableTyp firstByte |= ITypeMarshalBuffer.FLAG2; Long num= val.numericalValue(); if (num != null) { - long l= num; - if (l >= 0 && l <= Short.MAX_VALUE) { - nval= (short) l; + nval= num; + if (nval >= 0) { firstByte |= ITypeMarshalBuffer.FLAG3; } } @@ -190,7 +190,7 @@ public class CArrayType implements ICArrayType, ITypeContainer, ISerializableTyp buffer.putByte((byte) flags); } if (nval >= 0) { - buffer.putShort(nval); + buffer.putLong(nval); } else if (val != null) { buffer.marshalValue(val); } @@ -200,11 +200,11 @@ public class CArrayType implements ICArrayType, ITypeContainer, ISerializableTyp public static IType unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException { int flags= 0; IValue value= null; - if ( (firstByte & ITypeMarshalBuffer.FLAG1) != 0) { + if ((firstByte & ITypeMarshalBuffer.FLAG1) != 0) { flags= buffer.getByte(); } if ((firstByte & ITypeMarshalBuffer.FLAG3) != 0) { - value = Value.create(buffer.getShort()); + value = Value.create(buffer.getLong()); } else if ((firstByte & ITypeMarshalBuffer.FLAG2) != 0) { value = buffer.unmarshalValue(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunctionType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunctionType.java index e50497f3f96..7eda549d946 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunctionType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunctionType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2011 IBM Corporation and others. + * Copyright (c) 2004, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * Devin Steffler (IBM Corporation) - initial API and implementation * Markus Schorn (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; @@ -87,7 +88,7 @@ public class CFunctionType implements IFunctionType, ISerializableType { } else { firstByte |= ITypeMarshalBuffer.FLAG4; buffer.putByte((byte) firstByte); - buffer.putShort((short) len); + buffer.putInt(len); } buffer.marshalType(returnType); @@ -99,7 +100,7 @@ public class CFunctionType implements IFunctionType, ISerializableType { public static IType unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException { int len; if (((firstByte & ITypeMarshalBuffer.FLAG4) != 0)) { - len= buffer.getShort(); + len= buffer.getInt(); } else { len= (firstByte & (ITypeMarshalBuffer.FLAG4-1))/ITypeMarshalBuffer.FLAG1; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPArrayType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPArrayType.java index a832a347973..32555a25f86 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPArrayType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPArrayType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2010 IBM Corporation and others. + * Copyright (c) 2004, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * Andrew Niefer (IBM Corporation) - initial API and implementation * Markus Schorn (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -122,9 +123,9 @@ public class CPPArrayType implements IArrayType, ITypeContainer, ISerializableTy Long num= val.numericalValue(); if (num != null) { long lnum= num; - if (lnum >= 0 && lnum <= Short.MAX_VALUE) { + if (lnum >= 0) { buffer.putByte((byte) (firstByte | ITypeMarshalBuffer.FLAG1)); - buffer.putShort((short) lnum); + buffer.putLong(lnum); buffer.marshalType(getType()); return; } @@ -137,7 +138,7 @@ public class CPPArrayType implements IArrayType, ITypeContainer, ISerializableTy public static IType unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException { IValue value= null; if ((firstByte & ITypeMarshalBuffer.FLAG1) != 0) { - value = Value.create(buffer.getShort()); + value = Value.create(buffer.getLong()); } else if ((firstByte & ITypeMarshalBuffer.FLAG2) != 0) { value = buffer.unmarshalValue(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredClassInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredClassInstance.java index 3040eddf927..5b4cc473cc4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredClassInstance.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredClassInstance.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2011 IBM Corporation and others. + * Copyright (c) 2005, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -230,15 +230,16 @@ public class CPPDeferredClassInstance extends CPPUnknownBinding implements ICPPD int firstByte= ITypeMarshalBuffer.DEFERRED_CLASS_INSTANCE; buffer.putByte((byte) firstByte); buffer.marshalBinding(fClassTemplate); - buffer.putShort((short) fArguments.length); + buffer.putInt(fArguments.length); for (ICPPTemplateArgument arg : fArguments) { buffer.marshalTemplateArgument(arg); } } - public static ICPPDeferredClassInstance unmarshal(IIndexFragment fragment, int firstByte, ITypeMarshalBuffer buffer) throws CoreException { + public static ICPPDeferredClassInstance unmarshal(IIndexFragment fragment, int firstByte, + ITypeMarshalBuffer buffer) throws CoreException { IBinding template= buffer.unmarshalBinding(); - int argcount= buffer.getShort() & 0xffff; + int argcount= buffer.getInt(); ICPPTemplateArgument[] args = new ICPPTemplateArgument[argcount]; for (int i = 0; i < argcount; i++) { args[i]= buffer.unmarshalTemplateArgument(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionType.java index 7c07c5c8b0e..1655e0beba4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionType.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2011 IBM Corporation and others. + * Copyright (c) 2004, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * Andrew Niefer (IBM Corporation) - initial API and implementation * Markus Schorn (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -140,29 +141,17 @@ public class CPPFunctionType implements ICPPFunctionType, ISerializableType { if (isVolatile()) firstByte |= ITypeMarshalBuffer.FLAG2; if (takesVarArgs()) firstByte |= ITypeMarshalBuffer.FLAG3; - int len= (parameters.length & 0xffff); - if (len > 0xff) { - firstByte |= ITypeMarshalBuffer.FLAG4; - buffer.putByte((byte) firstByte); - buffer.putShort((short) len); - } else { - buffer.putByte((byte) firstByte); - buffer.putByte((byte) len); - } + buffer.putByte((byte) firstByte); + buffer.putInt(parameters.length); buffer.marshalType(returnType); - for (int i = 0; i < len; i++) { + for (int i = 0; i < parameters.length; i++) { buffer.marshalType(parameters[i]); } } public static IType unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException { - int len; - if (((firstByte & ITypeMarshalBuffer.FLAG4) != 0)) { - len= buffer.getShort(); - } else { - len= buffer.getByte(); - } + int len= buffer.getInt(); IType rt= buffer.unmarshalType(); IType[] pars= new IType[len]; for (int i = 0; i < pars.length; i++) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownClassInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownClassInstance.java index 12d96d5c75b..a48d638f138 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownClassInstance.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownClassInstance.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2010 Google, Inc and others. + * Copyright (c) 2008, 2012 Google, Inc and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -86,7 +86,7 @@ public class CPPUnknownClassInstance extends CPPUnknownMemberClass implements IC buffer.putByte((byte) firstByte); buffer.marshalType(getOwnerType()); buffer.putCharArray(getNameCharArray()); - buffer.putShort((short) arguments.length); + buffer.putInt(arguments.length); for (ICPPTemplateArgument arg : arguments) { buffer.marshalTemplateArgument(arg); } @@ -95,7 +95,7 @@ public class CPPUnknownClassInstance extends CPPUnknownMemberClass implements IC public static ICPPUnknownMemberClassInstance unmarshal(IIndexFragment fragment, int firstByte, ITypeMarshalBuffer buffer) throws CoreException { IType owner= buffer.unmarshalType(); char[] name = buffer.getCharArray(); - int argcount= buffer.getShort() & 0xffff; + int argcount= buffer.getInt(); ICPPTemplateArgument[] args = new ICPPTemplateArgument[argcount]; for (int i = 0; i < argcount; i++) { args[i]= buffer.unmarshalTemplateArgument(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPEvaluation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPEvaluation.java index 9c87b033846..762badaa597 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPEvaluation.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPEvaluation.java @@ -126,7 +126,7 @@ public abstract class CPPEvaluation implements ICPPEvaluation { } @Override - public void putShort(short value) { + public void putFixedInt(int value) { appendSeparator(); fBuffer.append(value); } @@ -192,7 +192,7 @@ public abstract class CPPEvaluation implements ICPPEvaluation { } @Override - public int getShort() throws CoreException { + public int getFixedInt() throws CoreException { throw new UnsupportedOperationException(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java index ea7f4f82be7..ea60a5169fc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java @@ -300,7 +300,7 @@ public class EvalBinding extends CPPEvaluation { // function and the parameter position instead. buffer.putByte((byte) (ITypeMarshalBuffer.EVAL_BINDING | ITypeMarshalBuffer.FLAG1)); buffer.marshalBinding(parameterOwner); - buffer.putShort((short) getFunctionParameterPosition()); + buffer.putInt(getFunctionParameterPosition()); } else { buffer.putByte(firstByte); buffer.marshalBinding(fBinding); @@ -311,7 +311,7 @@ public class EvalBinding extends CPPEvaluation { public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException { if ((firstByte & ITypeMarshalBuffer.FLAG1) != 0) { ICPPFunction parameterOwner= (ICPPFunction) buffer.unmarshalBinding(); - int parameterPosition= buffer.getShort(); + int parameterPosition= buffer.getInt(); IType type= buffer.unmarshalType(); return new EvalBinding(parameterOwner, parameterPosition, type); } else { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java index ea8d2a1ed97..b1821c5926a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java @@ -155,14 +155,14 @@ public class EvalComma extends CPPEvaluation { @Override public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { buffer.putByte(ITypeMarshalBuffer.EVAL_COMMA); - buffer.putShort((short) fArguments.length); + buffer.putInt(fArguments.length); for (ICPPEvaluation arg : fArguments) { buffer.marshalEvaluation(arg, includeValue); } } public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException { - int len= buffer.getShort(); + int len= buffer.getInt(); ICPPEvaluation[] args = new ICPPEvaluation[len]; for (int i = 0; i < args.length; i++) { args[i]= (ICPPEvaluation) buffer.unmarshalEvaluation(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java index 6218a972870..03f510189bb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java @@ -168,14 +168,14 @@ public class EvalFunctionCall extends CPPEvaluation { @Override public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { buffer.putByte(ITypeMarshalBuffer.EVAL_FUNCTION_CALL); - buffer.putShort((short) fArguments.length); + buffer.putInt(fArguments.length); for (ICPPEvaluation arg : fArguments) { buffer.marshalEvaluation(arg, includeValue); } } public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException { - int len= buffer.getShort(); + int len= buffer.getInt(); ICPPEvaluation[] args = new ICPPEvaluation[len]; for (int i = 0; i < args.length; i++) { args[i]= (ICPPEvaluation) buffer.unmarshalEvaluation(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java index 4e16f5a0751..f202f82778f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java @@ -110,12 +110,12 @@ public class EvalFunctionSet extends CPPEvaluation { firstByte |= ITypeMarshalBuffer.FLAG2; buffer.putByte((byte) firstByte); - buffer.putShort((short) bindings.length); + buffer.putInt(bindings.length); for (ICPPFunction binding : bindings) { buffer.marshalBinding(binding); } if (args != null) { - buffer.putShort((short) args.length); + buffer.putInt(args.length); for (ICPPTemplateArgument arg : args) { buffer.marshalTemplateArgument(arg); } @@ -124,14 +124,14 @@ public class EvalFunctionSet extends CPPEvaluation { public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException { final boolean addressOf= (firstByte & ITypeMarshalBuffer.FLAG1) != 0; - int bindingCount= buffer.getShort(); + int bindingCount= buffer.getInt(); ICPPFunction[] bindings= new ICPPFunction[bindingCount]; for (int i = 0; i < bindings.length; i++) { bindings[i]= (ICPPFunction) buffer.unmarshalBinding(); } ICPPTemplateArgument[] args= null; if ((firstByte & ITypeMarshalBuffer.FLAG2) != 0) { - int len= buffer.getShort(); + int len= buffer.getInt(); args = new ICPPTemplateArgument[len]; for (int i = 0; i < args.length; i++) { args[i]= buffer.unmarshalTemplateArgument(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java index 501189404f1..2f78b975479 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java @@ -151,7 +151,7 @@ public class EvalID extends CPPEvaluation { buffer.putCharArray(fName); buffer.marshalBinding(fNameOwner); if (fTemplateArgs != null) { - buffer.putShort((short) fTemplateArgs.length); + buffer.putInt(fTemplateArgs.length); for (ICPPTemplateArgument arg : fTemplateArgs) { buffer.marshalTemplateArgument(arg); } @@ -166,7 +166,7 @@ public class EvalID extends CPPEvaluation { IBinding nameOwner= buffer.unmarshalBinding(); ICPPTemplateArgument[] args= null; if ((firstByte & ITypeMarshalBuffer.FLAG3) != 0) { - int len= buffer.getShort(); + int len= buffer.getInt(); args = new ICPPTemplateArgument[len]; for (int i = 0; i < args.length; i++) { args[i]= buffer.unmarshalTemplateArgument(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java index 996f71a9e62..09355929a34 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java @@ -87,14 +87,14 @@ public class EvalInitList extends CPPEvaluation { @Override public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { buffer.putByte(ITypeMarshalBuffer.EVAL_INIT_LIST); - buffer.putShort((short) fClauses.length); + buffer.putInt(fClauses.length); for (ICPPEvaluation arg : fClauses) { buffer.marshalEvaluation(arg, includeValue); } } public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException { - int len= buffer.getShort(); + int len= buffer.getInt(); ICPPEvaluation[] args = new ICPPEvaluation[len]; for (int i = 0; i < args.length; i++) { args[i]= (ICPPEvaluation) buffer.unmarshalEvaluation(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java index 62f713dc1b9..b00f13229f3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java @@ -123,7 +123,7 @@ public class EvalTypeId extends CPPEvaluation { buffer.putByte((byte) firstByte); buffer.marshalType(fInputType); if (includeValue) { - buffer.putShort((short) fArguments.length); + buffer.putInt(fArguments.length); for (ICPPEvaluation arg : fArguments) { buffer.marshalEvaluation(arg, includeValue); } @@ -134,7 +134,7 @@ public class EvalTypeId extends CPPEvaluation { IType type= buffer.unmarshalType(); ICPPEvaluation[] args= null; if ((firstByte & ITypeMarshalBuffer.FLAG1) != 0) { - int len= buffer.getShort(); + int len= buffer.getInt(); args = new ICPPEvaluation[len]; for (int i = 0; i < args.length; i++) { args[i]= (ICPPEvaluation) buffer.unmarshalEvaluation(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index 18848bc3c32..5e9c268d982 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -222,10 +222,11 @@ public class PDOM extends PlatformObject implements IPDOM { * 128.0 - Preservation of typedefs in template arguments. * 129.0 - Merged several changes affecting index from the master branch. * 130.0 - Constexpr functions, bug 395238. + * 131.0 - More efficient and robust storage of types and template arguments, bug 395243. */ - private static final int MIN_SUPPORTED_VERSION= version(130, 0); - private static final int MAX_SUPPORTED_VERSION= version(130, Short.MAX_VALUE); - private static final int DEFAULT_VERSION = version(130, 0); + private static final int MIN_SUPPORTED_VERSION= version(131, 0); + private static final int MAX_SUPPORTED_VERSION= version(131, Short.MAX_VALUE); + private static final int DEFAULT_VERSION = version(131, 0); private static int version(int major, int minor) { return (major << 16) + minor; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java index 7951f04b21f..78c7670e9b5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java @@ -76,6 +76,8 @@ public class Database { public static final int MAX_BLOCK_DELTAS = CHUNK_SIZE / BLOCK_SIZE_DELTA; public static final int MAX_MALLOC_SIZE = MAX_BLOCK_DELTAS * BLOCK_SIZE_DELTA - BLOCK_HEADER_SIZE; public static final int PTR_SIZE = 4; // size of a pointer in the database in bytes + // The lower bound for TYPE_SIZE is 1 + PTR_SIZE, but a slightly larger space for types stored + // inline produces in a slightly smaller overall database size. public static final int TYPE_SIZE = 2 + PTR_SIZE; // size of a type in the database in bytes public static final int VALUE_SIZE = TYPE_SIZE; // size of a value in the database in bytes public static final int EVALUATION_SIZE = TYPE_SIZE; // size of an evaluation in the database in bytes diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/TypeMarshalBuffer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/TypeMarshalBuffer.java index c82ed116aa4..ac6d4058964 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/TypeMarshalBuffer.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/TypeMarshalBuffer.java @@ -33,7 +33,7 @@ import org.eclipse.core.runtime.CoreException; /** * For marshalling types to byte arrays. */ -public class TypeMarshalBuffer implements ITypeMarshalBuffer { +public final class TypeMarshalBuffer implements ITypeMarshalBuffer { public static final byte[] EMPTY= { 0, 0, 0, 0, 0, 0 }; public static final byte NULL_TYPE= 0; public static final byte INDIRECT_TYPE= (byte) -1; @@ -69,6 +69,11 @@ public class TypeMarshalBuffer implements ITypeMarshalBuffer { return fPos; } + public void setPosition(int pos) { + assert 0 <= pos && pos <= fPos; + fPos = pos; + } + public byte[] getBuffer() { return fBuffer; } @@ -257,23 +262,7 @@ public class TypeMarshalBuffer implements ITypeMarshalBuffer { } @Override - public void putShort(short value) { - request(2); - fBuffer[fPos++]= (byte) (value >> 8); - fBuffer[fPos++]= (byte) (value); - } - - @Override - public int getShort() throws CoreException { - if (fPos + 2 > fBuffer.length) - throw unmarshallingError(); - final int byte1 = 0xff & fBuffer[fPos++]; - final int byte2 = 0xff & fBuffer[fPos++]; - return (((byte1 << 8) | (byte2 & 0xff))); - } - - @Override - public void putInt(int value) { + public void putFixedInt(int value) { request(4); fPos += 4; int p= fPos; @@ -284,7 +273,7 @@ public class TypeMarshalBuffer implements ITypeMarshalBuffer { } @Override - public int getInt() throws CoreException { + public int getFixedInt() throws CoreException { if (fPos + 4 > fBuffer.length) throw unmarshallingError(); int result= 0; @@ -295,35 +284,48 @@ public class TypeMarshalBuffer implements ITypeMarshalBuffer { return result; } + @Override + public void putInt(int value) { + do { + int b = value & 0x7F; + value >>>= 7; + if (value != 0) + b |= 0x80; + putByte((byte) b); + } while (value != 0); + } + @Override public void putLong(long value) { - request(8); - fPos += 8; - int p= fPos; - fBuffer[--p]= (byte) (value); value >>= 8; - fBuffer[--p]= (byte) (value); value >>= 8; - fBuffer[--p]= (byte) (value); value >>= 8; - fBuffer[--p]= (byte) (value); value >>= 8; - fBuffer[--p]= (byte) (value); value >>= 8; - fBuffer[--p]= (byte) (value); value >>= 8; - fBuffer[--p]= (byte) (value); value >>= 8; - fBuffer[--p]= (byte) (value); + do { + int b = (int) value & 0x7F; + value >>>= 7; + if (value != 0) + b |= 0x80; + putByte((byte) b); + } while (value != 0); + } + + @Override + public int getInt() throws CoreException { + int b = getByte(); + int value = b & 0x7F; + for (int shift = 7; (b & 0x80) != 0; shift += 7) { + b = getByte(); + value |= (b & 0x7F) << shift; + } + return value; } @Override public long getLong() throws CoreException { - if (fPos + 8 > fBuffer.length) - throw unmarshallingError(); - long result= 0; - result |= fBuffer[fPos++] & 0xff; result <<= 8; - result |= fBuffer[fPos++] & 0xff; result <<= 8; - result |= fBuffer[fPos++] & 0xff; result <<= 8; - result |= fBuffer[fPos++] & 0xff; result <<= 8; - result |= fBuffer[fPos++] & 0xff; result <<= 8; - result |= fBuffer[fPos++] & 0xff; result <<= 8; - result |= fBuffer[fPos++] & 0xff; result <<= 8; - result |= fBuffer[fPos++] & 0xff; - return result; + int b = getByte(); + long value = b & 0x7F; + for (int shift = 7; (b & 0x80) != 0; shift += 7) { + b = getByte(); + value |= (b & 0x7F) << shift; + } + return value; } private void putRecordPointer(long record) { @@ -344,19 +346,19 @@ public class TypeMarshalBuffer implements ITypeMarshalBuffer { @Override public void putCharArray(char[] chars) { - putShort((short) chars.length); + putInt(chars.length); for (char c : chars) { - putShort((short) c); + putInt(c & 0xFFFF); } } @Override public char[] getCharArray() throws CoreException { - int len= getShort(); - char[] expr= new char[len]; - for (int i = 0; i < expr.length; i++) { - expr[i]= (char) getShort(); + int len= getInt(); + char[] chars= new char[len]; + for (int i = 0; i < chars.length; i++) { + chars[i]= (char) getInt(); } - return expr; + return chars; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java index 7c699dfc9b3..a0b15d7ed01 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java @@ -60,7 +60,7 @@ import org.eclipse.core.runtime.IProgressMonitor; * link time. These are generally global symbols specific to a given language. */ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage, IIndexBindingConstants { - // record offsets + // Record offsets. private static final int ID_OFFSET = PDOMNamedNode.RECORD_SIZE + 0; private static final int NEXT_OFFSET = PDOMNamedNode.RECORD_SIZE + 4; private static final int INDEX_OFFSET = PDOMNamedNode.RECORD_SIZE + 8; @@ -71,7 +71,7 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage protected static final int RECORD_SIZE = PDOMNamedNode.RECORD_SIZE + 20; protected static final long[] FILE_LOCAL_REC_DUMMY = new long[]{0}; - // node types + // Node types protected static final int LINKAGE= 0; // special one for myself private BTree fMacroIndex= null; // No need for volatile, all fields of BTree are final. @@ -447,12 +447,14 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage if (len > 0) { if (len <= maxInlineSize) { db.putBytes(offset, buf.getBuffer(), len); - } else { + } else { db.putByte(offset, TypeMarshalBuffer.INDIRECT_TYPE); long chainOffset = offset + 1; + buf.putInt(len); + int lenSize = buf.getPosition() - len; int bufferPos = 0; while (bufferPos < len) { - int chunkLength = len - bufferPos + 2; + int chunkLength = bufferPos == 0 ? len + lenSize : len - bufferPos; boolean chainingRequired = false; if (chunkLength > Database.MAX_MALLOC_SIZE) { chunkLength = Database.MAX_MALLOC_SIZE; @@ -460,36 +462,52 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage } long ptr = db.malloc(chunkLength); db.putRecPtr(chainOffset, ptr); - db.putShort(ptr, (short) len); - int pos = 2; + if (bufferPos == 0) { + // Write length. + db.putBytes(ptr, buf.getBuffer(), len, lenSize); + ptr += lenSize; + chunkLength -= lenSize; + } if (chainingRequired) { // Reserve space for the chaining pointer. - chainOffset = ptr + 2; pos += Database.PTR_SIZE; + chainOffset = ptr; + ptr += Database.PTR_SIZE; + chunkLength -= Database.PTR_SIZE; } - chunkLength -= pos; - db.putBytes(ptr + pos, buf.getBuffer(), bufferPos, chunkLength); + db.putBytes(ptr, buf.getBuffer(), bufferPos, chunkLength); bufferPos += chunkLength; } + buf.setPosition(len); // Restore buffer position. } } } private byte[] loadLinkedSerializedData(final Database db, long offset) throws CoreException { long ptr= db.getRecPtr(offset); - int len= db.getShort(ptr) & 0xffff; + // Read the length in variable-length base-128 encoding, see ITypeMarshalBuffer.putInt(int). + int pos = 0; + int b = db.getByte(ptr + pos++); + int len = b & 0x7F; + for (int shift = 7; (b & 0x80) != 0; shift += 7) { + b = db.getByte(ptr + pos++); + len |= (b & 0x7F) << shift; + } + byte[] data= new byte[len]; int bufferPos = 0; while (bufferPos < len) { - int chunkLength = len - bufferPos + 2; - int pos = 2; - long chunkPtr = ptr; + int chunkLength = len + pos - bufferPos; + long chunkPtr = ptr + pos; if (chunkLength > Database.MAX_MALLOC_SIZE) { chunkLength = Database.MAX_MALLOC_SIZE; - ptr= db.getRecPtr(chunkPtr + pos); pos += Database.PTR_SIZE; + ptr= db.getRecPtr(chunkPtr); + chunkPtr += Database.PTR_SIZE; + chunkLength -= Database.PTR_SIZE; } - chunkLength -= pos; - db.getBytes(chunkPtr + pos, data, bufferPos, chunkLength); + chunkLength -= pos; + db.getBytes(chunkPtr, data, bufferPos, chunkLength); bufferPos += chunkLength; + pos = 0; } return data; } @@ -497,18 +515,26 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage private void deleteSerializedData(Database db, long offset, int maxInlineSize) throws CoreException { byte firstByte= db.getByte(offset); if (firstByte == TypeMarshalBuffer.INDIRECT_TYPE) { - long ptr= db.getRecPtr(offset + 1); - int len= db.getShort(ptr) & 0xffff; + long chunkPtr= db.getRecPtr(offset + 1); + long ptr = chunkPtr; + // Read the length in variable-length base-128 encoding, see ITypeMarshalBuffer.putInt(int). + int b = db.getByte(ptr++); + int len = b & 0x7F; + for (int shift = 7; (b & 0x80) != 0; shift += 7) { + b = db.getByte(ptr++); + len |= (b & 0x7F) << shift; + } + + len += ptr - chunkPtr; while (len > 0) { - int chunkLength = len + 2; - int pos = 2; - long chunkPtr = ptr; + int chunkLength = len; if (chunkLength > Database.MAX_MALLOC_SIZE) { chunkLength = Database.MAX_MALLOC_SIZE; - ptr= db.getRecPtr(chunkPtr + pos); pos += Database.PTR_SIZE; + ptr= db.getRecPtr(ptr); + chunkLength -= Database.PTR_SIZE; } - chunkLength -= pos; db.free(chunkPtr); + chunkPtr = ptr; len -= chunkLength; } }