/// <summary>
/// Writes out the constants to the SWF file. This will also re-set the tables in the
/// code object, so be sure you don't have anything in there that you need.
/// </summary>
/// <param name="writer">Where to write the constants to.</param>
/// <param name="code">The code object with the tables in it, that we'll
/// overwrite.</param>
private void WriteConstantPool(ABCDataTypeWriter writer, AbcCode code)
{
/* Integer constants */
int[] ints = this.intMarshal.ToArray();
writer.WriteU30Packed((uint)(ints.Length == 1 ? 0 : ints.Length));
for (int i = 1; i < ints.Length; i++) /* Omit value at [0] */
{
#if DEBUG
this.writeLog.AppendLine("Const int #" + i + ": " + ints[i]);
#endif
writer.WriteSI32(ints[i]);
}
code.IntConsts = ints;
/* Unsigned integer constants */
uint[] uints = this.uintMarshal.ToArray();
writer.WriteU30Packed((uint)(uints.Length == 1 ? 0 : uints.Length));
for (int i = 1; i < uints.Length; i++) /* Omit value at [0] */
{
#if DEBUG
this.writeLog.AppendLine("Const uint #" + i + ": " + uints[i]);
#endif
writer.WriteUI32(uints[i]);
}
code.UIntConsts = uints;
/* Double constants */
ulong[] doubles = this.doubleMarshal.ToArray();
writer.WriteU30Packed((uint)(doubles.Length == 1 ? 0 : doubles.Length));
for (int i = 1; i < doubles.Length; i++) /* Omit value at [0] */
{
#if DEBUG
this.writeLog.AppendLine("Const double (bits) #" + i + ": " + doubles[i]);
#endif
/* We hack this here instead of having a U64 type, because it's a hack around not
* treating double properly. There's no such thing as U64 in SWF. */
ulong d = doubles[i];
uint low = (uint)(d & 0x00000000FFFFFFFF);
d >>= 32;
uint high = (uint)(d & 0x00000000FFFFFFFF);
writer.WriteUI32(high);
writer.WriteUI32(low);
}
code.DoubleConsts = doubles;
/* String constants */
string[] strings = this.stringMarshal.ToArray();
writer.WriteU30Packed((uint)(strings.Length == 1 ? 0 : strings.Length));
for (int i = 1; i < strings.Length; i++) /* Omit value at [0] */
{
#if DEBUG
this.writeLog.AppendLine("Const string #" + i + ": \"" + strings[i] + "\"");
#endif
writer.WriteString(strings[i]);
}
code.StringConsts = strings;
/* Namespace constants */
Namespace[] namespaces = this.nsMarshal.ToArray();
writer.WriteU30Packed((uint)(namespaces.Length == 1 ? 0 : namespaces.Length));
for (int i = 1; i < namespaces.Length; i++) /* Omit value at [0] */
{
#if DEBUG
this.writeLog.AppendLine("Const ns #" + i + ": " + namespaces[i]);
#endif
Namespace ns = namespaces[i];
writer.WriteUI8((uint)ns.Kind);
writer.WriteU30Packed((uint)this.stringMarshal.GetExistingIDFor(ns.Name));
}
code.SetNamespaces(namespaces);
/* Namespace set constants */
NamespaceSet[] namespaceSets = this.nsSetMarshal.ToArray();
writer.WriteU30Packed((uint)(namespaceSets.Length == 1 ? 0 : namespaceSets.Length));
for (int i = 1; i < namespaceSets.Length; i++) /* Omit value at [0] */
{
#if DEBUG
this.writeLog.AppendLine("Const ns set #" + i + ": " + namespaceSets[i]);
#endif
NamespaceSet nss = namespaceSets[i];
writer.WriteU30Packed((uint)nss.Count);
foreach (Namespace ns in nss)
{
writer.WriteU30Packed((uint)this.nsMarshal.GetExistingIDFor(ns));
}
}
code.SetNamespaceSets(namespaceSets);
/* Multiname constants */
Multiname[] multinames = this.multinameMarshal.ToArray();
writer.WriteU30Packed((uint)(multinames.Length == 1 ? 0 : multinames.Length));
for (int i = 1; i < multinames.Length; i++) /* Omit value at [0] */
{
#if DEBUG
this.writeLog.AppendLine("Const mn set #" + i + ": " + multinames[i]);
#endif
Multiname mn = multinames[i];
writer.WriteUI8((uint)mn.Kind);
switch (mn.Kind)
{
case Multiname.MultinameKind.QName:
case Multiname.MultinameKind.QNameA:
uint nsIdx = (uint)this.nsMarshal.GetExistingIDFor(mn.NS);
uint nameIdx = (uint)this.stringMarshal.GetExistingIDFor(mn.Name);
writer.WriteU30Packed(nsIdx);
writer.WriteU30Packed(nameIdx);
break;
case Multiname.MultinameKind.RTQName:
case Multiname.MultinameKind.RTQNameA:
writer.WriteU30Packed((uint)this.stringMarshal.GetExistingIDFor(mn.Name));
break;
case Multiname.MultinameKind.RTQNameL:
case Multiname.MultinameKind.RTQNameLA:
/* No data */
break;
case Multiname.MultinameKind.Multiname:
case Multiname.MultinameKind.MultinameA:
writer.WriteU30Packed((uint)this.stringMarshal.GetExistingIDFor(mn.Name));
writer.WriteU30Packed((uint)this.nsSetMarshal.GetExistingIDFor(mn.Set));
break;
case Multiname.MultinameKind.MultinameL:
case Multiname.MultinameKind.MultinameLA:
writer.WriteU30Packed((uint)this.nsSetMarshal.GetExistingIDFor(mn.Set));
break;
default:
break;
}
}
code.SetMultinames(multinames);
}