package com.ctc.wstx.api;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLReporter;
import org.codehaus.stax2.XMLOutputFactory2;
import org.codehaus.stax2.XMLStreamProperties;
import org.codehaus.stax2.io.EscapingWriterFactory;
import com.ctc.wstx.cfg.OutputConfigFlags;
import com.ctc.wstx.io.BufferRecycler;
import com.ctc.wstx.util.ArgUtil;
import com.ctc.wstx.util.DataUtil;
public final class WriterConfig
extends CommonConfig
implements OutputConfigFlags
{
protected final static String DEFAULT_AUTOMATIC_NS_PREFIX = "wstxns";
final static int PROP_AUTOMATIC_NS = 1;
final static int PROP_AUTOMATIC_EMPTY_ELEMENTS = 2;
final static int PROP_AUTO_CLOSE_OUTPUT = 3;
final static int PROP_ENABLE_NS = 4;
final static int PROP_AUTOMATIC_NS_PREFIX = 5;
final static int PROP_TEXT_ESCAPER = 6;
final static int PROP_ATTR_VALUE_ESCAPER = 7;
final static int PROP_PROBLEM_REPORTER = 8;
final static int PROP_USE_DOUBLE_QUOTES_IN_XML_DECL = 10;
final static int PROP_OUTPUT_CDATA_AS_TEXT = 11;
final static int PROP_COPY_DEFAULT_ATTRS = 12;
final static int PROP_ESCAPE_CR = 13;
final static int PROP_ADD_SPACE_AFTER_EMPTY_ELEM = 14;
final static int PROP_AUTOMATIC_END_ELEMENTS = 15;
final static int PROP_VALIDATE_STRUCTURE = 16;
final static int PROP_VALIDATE_CONTENT = 17;
final static int PROP_VALIDATE_ATTR = 18;
final static int PROP_VALIDATE_NAMES = 19;
final static int PROP_FIX_CONTENT = 20;
final static int PROP_OUTPUT_INVALID_CHAR_HANDLER = 21;
final static int PROP_OUTPUT_EMPTY_ELEMENT_HANDLER = 22;
final static int PROP_UNDERLYING_STREAM = 30;
final static int PROP_UNDERLYING_WRITER = 31;
final static boolean DEFAULT_USE_DOUBLE_QUOTES_IN_XML_DECL = false;
final static boolean DEFAULT_OUTPUT_CDATA_AS_TEXT = false;
final static boolean DEFAULT_COPY_DEFAULT_ATTRS = false;
final static boolean DEFAULT_ESCAPE_CR = true;
final static boolean DEFAULT_ADD_SPACE_AFTER_EMPTY_ELEM = false;
final static boolean DEFAULT_VALIDATE_STRUCTURE = true;
final static boolean DEFAULT_VALIDATE_CONTENT = true;
final static boolean DEFAULT_VALIDATE_ATTR = false;
final static boolean DEFAULT_VALIDATE_NAMES = false;
final static boolean DEFAULT_FIX_CONTENT = false;
final static int DEFAULT_FLAGS_J2ME =
0
| CFG_ENABLE_NS
| CFG_AUTOMATIC_EMPTY_ELEMENTS
| (DEFAULT_USE_DOUBLE_QUOTES_IN_XML_DECL ? CFG_USE_DOUBLE_QUOTES_IN_XML_DECL : 0)
| (DEFAULT_OUTPUT_CDATA_AS_TEXT ? CFG_OUTPUT_CDATA_AS_TEXT : 0)
| (DEFAULT_COPY_DEFAULT_ATTRS ? CFG_COPY_DEFAULT_ATTRS : 0)
| (DEFAULT_ESCAPE_CR ? CFG_ESCAPE_CR : 0)
| (DEFAULT_ADD_SPACE_AFTER_EMPTY_ELEM ? CFG_ADD_SPACE_AFTER_EMPTY_ELEM : 0)
| CFG_AUTOMATIC_END_ELEMENTS
| (DEFAULT_VALIDATE_STRUCTURE ? CFG_VALIDATE_STRUCTURE : 0)
| (DEFAULT_VALIDATE_CONTENT ? CFG_VALIDATE_CONTENT : 0)
| (DEFAULT_VALIDATE_ATTR ? CFG_VALIDATE_ATTR : 0)
| (DEFAULT_VALIDATE_NAMES ? CFG_VALIDATE_NAMES : 0)
| (DEFAULT_FIX_CONTENT ? CFG_FIX_CONTENT : 0)
;
final static int DEFAULT_FLAGS_FULL = DEFAULT_FLAGS_J2ME;
final static HashMap<String,Integer> sProperties = new HashMap<String,Integer>(8);
static {
sProperties.put(XMLOutputFactory.IS_REPAIRING_NAMESPACES,
DataUtil.Integer(PROP_AUTOMATIC_NS));
sProperties.put(XMLStreamProperties.XSP_NAMESPACE_AWARE,
DataUtil.Integer(PROP_ENABLE_NS));
sProperties.put(XMLOutputFactory2.P_AUTOMATIC_EMPTY_ELEMENTS,
DataUtil.Integer(PROP_AUTOMATIC_EMPTY_ELEMENTS));
sProperties.put(XMLOutputFactory2.P_AUTO_CLOSE_OUTPUT,
DataUtil.Integer(PROP_AUTO_CLOSE_OUTPUT));
sProperties.put(XMLOutputFactory2.P_AUTOMATIC_NS_PREFIX,
DataUtil.Integer(PROP_AUTOMATIC_NS_PREFIX));
sProperties.put(XMLOutputFactory2.P_TEXT_ESCAPER,
DataUtil.Integer(PROP_TEXT_ESCAPER));
sProperties.put(XMLOutputFactory2.P_ATTR_VALUE_ESCAPER,
DataUtil.Integer(PROP_ATTR_VALUE_ESCAPER));
sProperties.put(XMLStreamProperties.XSP_PROBLEM_REPORTER,
DataUtil.Integer(PROP_PROBLEM_REPORTER));
sProperties.put(WstxOutputProperties.P_USE_DOUBLE_QUOTES_IN_XML_DECL,
DataUtil.Integer(PROP_USE_DOUBLE_QUOTES_IN_XML_DECL));
sProperties.put(WstxOutputProperties.P_OUTPUT_CDATA_AS_TEXT,
DataUtil.Integer(PROP_OUTPUT_CDATA_AS_TEXT));
sProperties.put(WstxOutputProperties.P_COPY_DEFAULT_ATTRS,
DataUtil.Integer(PROP_COPY_DEFAULT_ATTRS));
sProperties.put(WstxOutputProperties.P_OUTPUT_ESCAPE_CR,
DataUtil.Integer(PROP_ESCAPE_CR));
sProperties.put(WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM,
DataUtil.Integer(PROP_ADD_SPACE_AFTER_EMPTY_ELEM));
sProperties.put(WstxOutputProperties.P_AUTOMATIC_END_ELEMENTS,
DataUtil.Integer(PROP_AUTOMATIC_END_ELEMENTS));
sProperties.put(WstxOutputProperties.P_OUTPUT_INVALID_CHAR_HANDLER,
DataUtil.Integer(PROP_OUTPUT_INVALID_CHAR_HANDLER));
sProperties.put(WstxOutputProperties.P_OUTPUT_EMPTY_ELEMENT_HANDLER,
DataUtil.Integer(PROP_OUTPUT_EMPTY_ELEMENT_HANDLER));
sProperties.put(WstxOutputProperties.P_OUTPUT_VALIDATE_STRUCTURE,
DataUtil.Integer(PROP_VALIDATE_STRUCTURE));
sProperties.put(WstxOutputProperties.P_OUTPUT_VALIDATE_CONTENT,
DataUtil.Integer(PROP_VALIDATE_CONTENT));
sProperties.put(WstxOutputProperties.P_OUTPUT_VALIDATE_ATTR,
DataUtil.Integer(PROP_VALIDATE_ATTR));
sProperties.put(WstxOutputProperties.P_OUTPUT_VALIDATE_NAMES,
DataUtil.Integer(PROP_VALIDATE_NAMES));
sProperties.put(WstxOutputProperties.P_OUTPUT_FIX_CONTENT,
DataUtil.Integer(PROP_FIX_CONTENT));
sProperties.put(WstxOutputProperties.P_OUTPUT_UNDERLYING_STREAM,
DataUtil.Integer(PROP_UNDERLYING_STREAM));
sProperties.put(WstxOutputProperties.P_OUTPUT_UNDERLYING_STREAM,
DataUtil.Integer(PROP_UNDERLYING_STREAM));
}
final boolean mIsJ2MESubset;
protected int mConfigFlags;
Object[] mSpecialProperties = null;
private final static int SPEC_PROC_COUNT = 6;
private final static int SP_IX_AUTO_NS_PREFIX = 0;
private final static int SP_IX_TEXT_ESCAPER_FACTORY = 1;
private final static int SP_IX_ATTR_VALUE_ESCAPER_FACTORY = 2;
private final static int SP_IX_PROBLEM_REPORTER = 3;
private final static int SP_IX_INVALID_CHAR_HANDLER = 4;
private final static int SP_IX_EMPTY_ELEMENT_HANDLER = 5;
final static ThreadLocal<SoftReference<BufferRecycler>> mRecyclerRef = new ThreadLocal<SoftReference<BufferRecycler>>();
BufferRecycler mCurrRecycler = null;
private WriterConfig(WriterConfig base,
boolean j2meSubset, int flags, Object[] specProps)
{
super(base);
mIsJ2MESubset = j2meSubset;
mConfigFlags = flags;
mSpecialProperties = specProps;
SoftReference<BufferRecycler> ref = mRecyclerRef.get();
if (ref != null) {
mCurrRecycler = ref.get();
}
}
public static WriterConfig createJ2MEDefaults()
{
return new WriterConfig(null, true, DEFAULT_FLAGS_J2ME, null);
}
public static WriterConfig createFullDefaults()
{
return new WriterConfig(null, false, DEFAULT_FLAGS_FULL, null);
}
public WriterConfig createNonShared()
{
Object[] specProps;
if (mSpecialProperties != null) {
int len = mSpecialProperties.length;
specProps = new Object[len];
System.arraycopy(mSpecialProperties, 0, specProps, 0, len);
} else {
specProps = null;
}
return new WriterConfig(this, mIsJ2MESubset, mConfigFlags, specProps);
}
@Override
protected int findPropertyId(String propName)
{
Integer I = sProperties.get(propName);
return (I == null) ? -1 : I.intValue();
}
@Override
public Object getProperty(int id)
{
switch (id) {
case PROP_AUTOMATIC_NS:
return automaticNamespacesEnabled() ? Boolean.TRUE : Boolean.FALSE;
case PROP_ENABLE_NS:
return willSupportNamespaces() ? Boolean.TRUE : Boolean.FALSE;
case PROP_PROBLEM_REPORTER:
return getProblemReporter();
case PROP_AUTOMATIC_EMPTY_ELEMENTS:
return automaticEmptyElementsEnabled() ? Boolean.TRUE : Boolean.FALSE;
case PROP_AUTO_CLOSE_OUTPUT:
return willAutoCloseOutput() ? Boolean.TRUE : Boolean.FALSE;
case PROP_AUTOMATIC_NS_PREFIX:
return getAutomaticNsPrefix();
case PROP_TEXT_ESCAPER:
return getTextEscaperFactory();
case PROP_ATTR_VALUE_ESCAPER:
return getAttrValueEscaperFactory();
case PROP_USE_DOUBLE_QUOTES_IN_XML_DECL:
return willUseDoubleQuotesInXmlDecl() ? Boolean.TRUE : Boolean.FALSE;
case PROP_OUTPUT_CDATA_AS_TEXT:
return willOutputCDataAsText() ? Boolean.TRUE : Boolean.FALSE;
case PROP_COPY_DEFAULT_ATTRS:
return willCopyDefaultAttrs() ? Boolean.TRUE : Boolean.FALSE;
case PROP_ESCAPE_CR:
return willEscapeCr() ? Boolean.TRUE : Boolean.FALSE;
case PROP_ADD_SPACE_AFTER_EMPTY_ELEM:
return willAddSpaceAfterEmptyElem() ? Boolean.TRUE : Boolean.FALSE;
case PROP_AUTOMATIC_END_ELEMENTS:
return automaticEndElementsEnabled() ? Boolean.TRUE : Boolean.FALSE;
case PROP_VALIDATE_STRUCTURE:
return willValidateStructure() ? Boolean.TRUE : Boolean.FALSE;
case PROP_VALIDATE_CONTENT:
return willValidateContent() ? Boolean.TRUE : Boolean.FALSE;
case PROP_VALIDATE_ATTR:
return willValidateAttributes() ? Boolean.TRUE : Boolean.FALSE;
case PROP_VALIDATE_NAMES:
return willValidateNames() ? Boolean.TRUE : Boolean.FALSE;
case PROP_FIX_CONTENT:
return willFixContent() ? Boolean.TRUE : Boolean.FALSE;
case PROP_OUTPUT_INVALID_CHAR_HANDLER:
return getInvalidCharHandler();
case PROP_OUTPUT_EMPTY_ELEMENT_HANDLER:
return getEmptyElementHandler();
case PROP_UNDERLYING_STREAM:
case PROP_UNDERLYING_WRITER:
throw new IllegalStateException("Can not access per-stream-writer properties via factory");
}
throw new IllegalStateException("Internal error: no handler for property with internal id "+id+".");
}
@Override
public boolean setProperty(String name, int id, Object value)
{
switch (id) {
case PROP_AUTOMATIC_NS:
enableAutomaticNamespaces(ArgUtil.convertToBoolean(name, value));
break;
case PROP_ENABLE_NS:
doSupportNamespaces(ArgUtil.convertToBoolean(name, value));
break;
case PROP_PROBLEM_REPORTER:
setProblemReporter((XMLReporter) value);
break;
case PROP_AUTOMATIC_EMPTY_ELEMENTS:
enableAutomaticEmptyElements(ArgUtil.convertToBoolean(name, value));
break;
case PROP_AUTO_CLOSE_OUTPUT:
doAutoCloseOutput(ArgUtil.convertToBoolean(name, value));
break;
case PROP_AUTOMATIC_NS_PREFIX:
setAutomaticNsPrefix(value.toString());
break;
case PROP_TEXT_ESCAPER:
setTextEscaperFactory((EscapingWriterFactory) value);
break;
case PROP_ATTR_VALUE_ESCAPER:
setAttrValueEscaperFactory((EscapingWriterFactory) value);
break;
case PROP_USE_DOUBLE_QUOTES_IN_XML_DECL:
doUseDoubleQuotesInXmlDecl(ArgUtil.convertToBoolean(name, value));
break;
case PROP_OUTPUT_CDATA_AS_TEXT:
doOutputCDataAsText(ArgUtil.convertToBoolean(name, value));
break;
case PROP_COPY_DEFAULT_ATTRS:
doCopyDefaultAttrs(ArgUtil.convertToBoolean(name, value));
break;
case PROP_ESCAPE_CR:
doEscapeCr(ArgUtil.convertToBoolean(name, value));
break;
case PROP_ADD_SPACE_AFTER_EMPTY_ELEM:
doAddSpaceAfterEmptyElem(ArgUtil.convertToBoolean(name, value));
break;
case PROP_AUTOMATIC_END_ELEMENTS:
enableAutomaticEndElements(ArgUtil.convertToBoolean(name, value));
break;
case PROP_VALIDATE_STRUCTURE:
doValidateStructure(ArgUtil.convertToBoolean(name, value));
break;
case PROP_VALIDATE_CONTENT:
doValidateContent(ArgUtil.convertToBoolean(name, value));
break;
case PROP_VALIDATE_ATTR:
doValidateAttributes(ArgUtil.convertToBoolean(name, value));
break;
case PROP_VALIDATE_NAMES:
doValidateNames(ArgUtil.convertToBoolean(name, value));
break;
case PROP_FIX_CONTENT:
doFixContent(ArgUtil.convertToBoolean(name, value));
break;
case PROP_OUTPUT_INVALID_CHAR_HANDLER:
setInvalidCharHandler((InvalidCharHandler) value);
break;
case PROP_OUTPUT_EMPTY_ELEMENT_HANDLER:
setEmptyElementHandler((EmptyElementHandler) value);
break;
case PROP_UNDERLYING_STREAM:
case PROP_UNDERLYING_WRITER:
throw new IllegalStateException("Can not modify per-stream-writer properties via factory");
default:
throw new IllegalStateException("Internal error: no handler for property with internal id "+id+".");
}
return true;
}
public int getConfigFlags() { return mConfigFlags; }
public boolean automaticNamespacesEnabled() {
return hasConfigFlag(CFG_AUTOMATIC_NS);
}
public boolean automaticEmptyElementsEnabled() {
return hasConfigFlag(CFG_AUTOMATIC_EMPTY_ELEMENTS);
}
public boolean willAutoCloseOutput() {
return hasConfigFlag(CFG_AUTO_CLOSE_OUTPUT);
}
public boolean willSupportNamespaces() {
return hasConfigFlag(CFG_ENABLE_NS);
}
public boolean willUseDoubleQuotesInXmlDecl() {
return hasConfigFlag(CFG_USE_DOUBLE_QUOTES_IN_XML_DECL);
}
public boolean willOutputCDataAsText() {
return hasConfigFlag(CFG_OUTPUT_CDATA_AS_TEXT);
}
public boolean willCopyDefaultAttrs() {
return hasConfigFlag(CFG_COPY_DEFAULT_ATTRS);
}
public boolean willEscapeCr() {
return hasConfigFlag(CFG_ESCAPE_CR);
}
public boolean willAddSpaceAfterEmptyElem() {
return hasConfigFlag(CFG_ADD_SPACE_AFTER_EMPTY_ELEM);
}
public boolean automaticEndElementsEnabled() {
return hasConfigFlag(CFG_AUTOMATIC_END_ELEMENTS);
}
public boolean willValidateStructure() {
return hasConfigFlag(CFG_VALIDATE_STRUCTURE);
}
public boolean willValidateContent() {
return hasConfigFlag(CFG_VALIDATE_CONTENT);
}
public boolean willValidateAttributes() {
return hasConfigFlag(CFG_VALIDATE_ATTR);
}
public boolean willValidateNames() {
return hasConfigFlag(CFG_VALIDATE_NAMES);
}
public boolean willFixContent() {
return hasConfigFlag(CFG_FIX_CONTENT);
}
public String getAutomaticNsPrefix() {
String prefix = (String) getSpecialProperty(SP_IX_AUTO_NS_PREFIX);
if (prefix == null) {
prefix = DEFAULT_AUTOMATIC_NS_PREFIX;
}
return prefix;
}
public EscapingWriterFactory getTextEscaperFactory() {
return (EscapingWriterFactory) getSpecialProperty(SP_IX_TEXT_ESCAPER_FACTORY);
}
public EscapingWriterFactory getAttrValueEscaperFactory() {
return (EscapingWriterFactory) getSpecialProperty(SP_IX_ATTR_VALUE_ESCAPER_FACTORY);
}
public XMLReporter getProblemReporter() {
return (XMLReporter) getSpecialProperty(SP_IX_PROBLEM_REPORTER);
}
public InvalidCharHandler getInvalidCharHandler() {
return (InvalidCharHandler) getSpecialProperty(SP_IX_INVALID_CHAR_HANDLER);
}
public EmptyElementHandler getEmptyElementHandler() {
return (EmptyElementHandler) getSpecialProperty(SP_IX_EMPTY_ELEMENT_HANDLER);
}
public void enableAutomaticNamespaces(boolean state) {
setConfigFlag(CFG_AUTOMATIC_NS, state);
}
public void enableAutomaticEmptyElements(boolean state) {
setConfigFlag(CFG_AUTOMATIC_EMPTY_ELEMENTS, state);
}
public void doAutoCloseOutput(boolean state) {
setConfigFlag(CFG_AUTO_CLOSE_OUTPUT, state);
}
public void doSupportNamespaces(boolean state) {
setConfigFlag(CFG_ENABLE_NS, state);
}
public void doUseDoubleQuotesInXmlDecl(boolean state) {
setConfigFlag(CFG_USE_DOUBLE_QUOTES_IN_XML_DECL, state);
}
public void doOutputCDataAsText(boolean state) {
setConfigFlag(CFG_OUTPUT_CDATA_AS_TEXT, state);
}
public void doCopyDefaultAttrs(boolean state) {
setConfigFlag(CFG_COPY_DEFAULT_ATTRS, state);
}
public void doEscapeCr(boolean state) {
setConfigFlag(CFG_ESCAPE_CR, state);
}
public void doAddSpaceAfterEmptyElem(boolean state) {
setConfigFlag(CFG_ADD_SPACE_AFTER_EMPTY_ELEM, state);
}
public void enableAutomaticEndElements(boolean state) {
setConfigFlag(CFG_AUTOMATIC_END_ELEMENTS, state);
}
public void doValidateStructure(boolean state) {
setConfigFlag(CFG_VALIDATE_STRUCTURE, state);
}
public void doValidateContent(boolean state) {
setConfigFlag(CFG_VALIDATE_CONTENT, state);
}
public void doValidateAttributes(boolean state) {
setConfigFlag(CFG_VALIDATE_ATTR, state);
}
public void doValidateNames(boolean state) {
setConfigFlag(CFG_VALIDATE_NAMES, state);
}
public void doFixContent(boolean state) {
setConfigFlag(CFG_FIX_CONTENT, state);
}
public void setAutomaticNsPrefix(String prefix) {
setSpecialProperty(SP_IX_AUTO_NS_PREFIX, prefix);
}
public void setTextEscaperFactory(EscapingWriterFactory f) {
setSpecialProperty(SP_IX_TEXT_ESCAPER_FACTORY, f);
}
public void setAttrValueEscaperFactory(EscapingWriterFactory f) {
setSpecialProperty(SP_IX_ATTR_VALUE_ESCAPER_FACTORY, f);
}
public void setProblemReporter(XMLReporter rep) {
setSpecialProperty(SP_IX_PROBLEM_REPORTER, rep);
}
public void setInvalidCharHandler(InvalidCharHandler h) {
setSpecialProperty(SP_IX_INVALID_CHAR_HANDLER, h);
}
public void setEmptyElementHandler(EmptyElementHandler h) {
setSpecialProperty(SP_IX_EMPTY_ELEMENT_HANDLER, h);
}
public void configureForXmlConformance()
{
doValidateAttributes(true);
doValidateContent(true);
doValidateStructure(true);
doValidateNames(true);
}
public void configureForRobustness()
{
doValidateAttributes(true);
doValidateStructure(true);
doValidateNames(true);
doValidateContent(true);
doFixContent(true);
}
public void configureForSpeed()
{
doValidateAttributes(false);
doValidateContent(false);
doValidateNames(false);
}
public char[] allocMediumCBuffer(int minSize)
{
if (mCurrRecycler != null) {
char[] result = mCurrRecycler.getMediumCBuffer(minSize);
if (result != null) {
return result;
}
}
return new char[minSize];
}
public void freeMediumCBuffer(char[] buffer)
{
if (mCurrRecycler == null) {
mCurrRecycler = createRecycler();
}
mCurrRecycler.returnMediumCBuffer(buffer);
}
public char[] allocFullCBuffer(int minSize)
{
if (mCurrRecycler != null) {
char[] result = mCurrRecycler.getFullCBuffer(minSize);
if (result != null) {
return result;
}
}
return new char[minSize];
}
public void freeFullCBuffer(char[] buffer)
{
if (mCurrRecycler == null) {
mCurrRecycler = createRecycler();
}
mCurrRecycler.returnFullCBuffer(buffer);
}
public byte[] allocFullBBuffer(int minSize)
{
if (mCurrRecycler != null) {
byte[] result = mCurrRecycler.getFullBBuffer(minSize);
if (result != null) {
return result;
}
}
return new byte[minSize];
}
public void freeFullBBuffer(byte[] buffer)
{
if (mCurrRecycler == null) {
mCurrRecycler = createRecycler();
}
mCurrRecycler.returnFullBBuffer(buffer);
}
private BufferRecycler createRecycler()
{
BufferRecycler recycler = new BufferRecycler();
mRecyclerRef.set(new SoftReference<BufferRecycler>(recycler));
return recycler;
}
private void setConfigFlag(int flag, boolean state) {
if (state) {
mConfigFlags |= flag;
} else {
mConfigFlags &= ~flag;
}
}
private final boolean hasConfigFlag(int flag) {
return ((mConfigFlags & flag) == flag);
}
private final Object getSpecialProperty(int ix)
{
if (mSpecialProperties == null) {
return null;
}
return mSpecialProperties[ix];
}
private final void setSpecialProperty(int ix, Object value)
{
if (mSpecialProperties == null) {
mSpecialProperties = new Object[SPEC_PROC_COUNT];
}
mSpecialProperties[ix] = value;
}
}