[prev in list] [next in list] [prev in thread] [next in thread]
List: avro-commits
Subject: svn commit: r1540206 [1/2] - in /avro/trunk/lang/csharp/src/apache: main/Generic/ main/Specific/ per
From: cutting () apache ! org
Date: 2013-11-08 22:15:03
Message-ID: 20131108221503.C0C8B23888E7 () eris ! apache ! org
[Download RAW message or body]
Author: cutting
Date: Fri Nov 8 22:15:02 2013
New Revision: 1540206
URL: http://svn.apache.org/r1540206
Log:
AVRO-1332. Add missing files and fix a bug with defaults. Contributed by David \
McIntosh.
Added:
avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumReader.cs
avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumWriter.cs
avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumReader.cs
avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumWriter.cs
avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumReader.cs
avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumWriter.cs
avro/trunk/lang/csharp/src/apache/perf/
avro/trunk/lang/csharp/src/apache/perf/Avro.perf.csproj
avro/trunk/lang/csharp/src/apache/perf/PerfTest.cs
avro/trunk/lang/csharp/src/apache/perf/com/
avro/trunk/lang/csharp/src/apache/perf/com/foo/
avro/trunk/lang/csharp/src/apache/perf/com/foo/A.cs
avro/trunk/lang/csharp/src/apache/perf/com/foo/Complex.cs
avro/trunk/lang/csharp/src/apache/perf/com/foo/MyEnum.cs
avro/trunk/lang/csharp/src/apache/perf/com/foo/MyFixed.cs
avro/trunk/lang/csharp/src/apache/perf/com/foo/Narrow.cs
avro/trunk/lang/csharp/src/apache/perf/com/foo/Simple.cs
avro/trunk/lang/csharp/src/apache/perf/com/foo/Wide.cs
avro/trunk/lang/csharp/src/apache/perf/com/foo/newRec.cs
avro/trunk/lang/csharp/src/apache/perf/schema.avsc
Modified:
avro/trunk/lang/csharp/src/apache/test/Generic/GenericTests.cs
Added: avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumReader.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumReader.cs?rev=1540206&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumReader.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumReader.cs Fri Nov 8 \
22:15:02 2013 @@ -0,0 +1,211 @@
+ï » ¿/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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.
+ */
+using System;
+using System.Collections.Generic;
+using Avro.IO;
+
+namespace Avro.Generic
+{
+ /// PreresolvingDatumReader for reading data to GenericRecord classes or \
primitives. + /// <see cref="PreresolvingDatumReader{T}">For more information \
about performance considerations for choosing this implementation</see> + public \
class GenericDatumReader<T> : PreresolvingDatumReader<T> + {
+ public GenericDatumReader(Schema writerSchema, Schema readerSchema) : \
base(writerSchema, readerSchema) + {
+ }
+
+ protected override bool IsReusable(Schema.Type tag)
+ {
+ switch (tag)
+ {
+ case Schema.Type.Double:
+ case Schema.Type.Boolean:
+ case Schema.Type.Int:
+ case Schema.Type.Long:
+ case Schema.Type.Float:
+ case Schema.Type.Bytes:
+ case Schema.Type.String:
+ case Schema.Type.Null:
+ return false;
+ }
+ return true;
+ }
+
+ protected override ArrayAccess GetArrayAccess(ArraySchema readerSchema)
+ {
+ return new GenericArrayAccess();
+ }
+
+ protected override EnumAccess GetEnumAccess(EnumSchema readerSchema)
+ {
+ return new GenericEnumAccess(readerSchema);
+ }
+
+ protected override MapAccess GetMapAccess(MapSchema readerSchema)
+ {
+ return new GenericMapAccess();
+ }
+
+ protected override RecordAccess GetRecordAccess(RecordSchema readerSchema)
+ {
+ return new GenericRecordAccess(readerSchema);
+ }
+
+ protected override FixedAccess GetFixedAccess(FixedSchema readerSchema)
+ {
+ return new GenericFixedAccess(readerSchema);
+ }
+
+ class GenericEnumAccess : EnumAccess
+ {
+ private EnumSchema schema;
+
+ public GenericEnumAccess(EnumSchema schema)
+ {
+ this.schema = schema;
+ }
+
+ public object CreateEnum(object reuse, int ordinal)
+ {
+ if (reuse is GenericEnum)
+ {
+ var ge = (GenericEnum) reuse;
+ if (ge.Schema.Equals(this.schema))
+ {
+ ge.Value = this.schema[ordinal];
+ return ge;
+ }
+ }
+ return new GenericEnum(this.schema, this.schema[ordinal]);
+ }
+ }
+
+ internal class GenericRecordAccess : RecordAccess
+ {
+ private RecordSchema schema;
+
+ public GenericRecordAccess(RecordSchema schema)
+ {
+ this.schema = schema;
+ }
+
+ public object CreateRecord(object reuse)
+ {
+ GenericRecord ru = (reuse == null || !(reuse is GenericRecord) || \
!(reuse as GenericRecord).Schema.Equals(this.schema)) ? + new \
GenericRecord(this.schema) : + reuse as GenericRecord;
+ return ru;
+ }
+
+ public object GetField(object record, string fieldName, int fieldPos)
+ {
+ object result;
+ if(!((GenericRecord)record).TryGetValue(fieldName, out result))
+ {
+ return null;
+ }
+ return result;
+ }
+
+ public void AddField(object record, string fieldName, int fieldPos, \
object fieldValue) + {
+ ((GenericRecord)record).Add(fieldName, fieldValue);
+ }
+ }
+
+ class GenericFixedAccess : FixedAccess
+ {
+ private FixedSchema schema;
+
+ public GenericFixedAccess(FixedSchema schema)
+ {
+ this.schema = schema;
+ }
+
+ public object CreateFixed(object reuse)
+ {
+ return (reuse is GenericFixed && (reuse as \
GenericFixed).Schema.Equals(this.schema)) ? + reuse : new \
GenericFixed(this.schema); + }
+
+ public byte[] GetFixedBuffer( object f )
+ {
+ return ((GenericFixed)f).Value;
+ }
+ }
+
+ class GenericArrayAccess : ArrayAccess
+ {
+ public object Create(object reuse)
+ {
+ return (reuse is object[]) ? reuse : new object[0];
+ }
+
+ public void EnsureSize(ref object array, int targetSize)
+ {
+ if (((object[])array).Length < targetSize)
+ SizeTo(ref array, targetSize);
+ }
+
+ public void Resize(ref object array, int targetSize)
+ {
+ SizeTo(ref array, targetSize);
+ }
+
+ public void AddElements( object arrayObj, int elements, int index, \
ReadItem itemReader, Decoder decoder, bool reuse ) + {
+ var array = (object[]) arrayObj;
+ for (int i = index; i < index + elements; i++)
+ {
+ array[i] = reuse ? itemReader(array[i], decoder) : \
itemReader(null, decoder); + }
+ }
+
+ private static void SizeTo(ref object array, int targetSize)
+ {
+ var o = (object[]) array;
+ Array.Resize(ref o, targetSize);
+ array = o;
+ }
+ }
+
+ class GenericMapAccess : MapAccess
+ {
+ public object Create(object reuse)
+ {
+ if (reuse is IDictionary<string, object>)
+ {
+ var result = (IDictionary<string, object>)reuse;
+ result.Clear();
+ return result;
+ }
+ return new Dictionary<string, object>();
+ }
+
+ public void AddElements(object mapObj, int elements, ReadItem \
itemReader, Decoder decoder, bool reuse) + {
+ var map = ((IDictionary<string, object>)mapObj);
+ for (int i = 0; i < elements; i++)
+ {
+ var key = decoder.ReadString();
+ map[key] = itemReader(null, decoder);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
Added: avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumWriter.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumWriter.cs?rev=1540206&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumWriter.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Generic/GenericDatumWriter.cs Fri Nov 8 \
22:15:02 2013 @@ -0,0 +1,147 @@
+ï » ¿/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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.
+ */
+using System;
+using System.Collections.Generic;
+using Encoder = Avro.IO.Encoder;
+
+namespace Avro.Generic
+{
+ /// <summary>
+ /// PreresolvingDatumWriter for writing data from GenericRecords or primitive \
types. + /// <see cref="PreresolvingDatumWriter{T}">For more information about \
performance considerations for choosing this implementation</see> + /// </summary>
+ public class GenericDatumWriter<T> : PreresolvingDatumWriter<T>
+ {
+ public GenericDatumWriter( Schema schema ) : base(schema, new \
GenericArrayAccess(), new DictionaryMapAccess()) + {
+ }
+
+ protected override void WriteRecordFields(object recordObj, \
RecordFieldWriter[] writers, Encoder encoder) + {
+ var record = (GenericRecord) recordObj;
+ foreach (var writer in writers)
+ {
+ writer.WriteField(record[writer.Field.Name], encoder);
+ }
+ }
+
+ protected override void EnsureRecordObject( RecordSchema recordSchema, \
object value ) + {
+ if( value == null || !( value is GenericRecord ) || !( ( value as \
GenericRecord ).Schema.Equals( recordSchema ) ) ) + {
+ throw TypeMismatch( value, "record", "GenericRecord" );
+ }
+ }
+
+ protected override void WriteField(object record, string fieldName, int \
fieldPos, WriteItem writer, Encoder encoder) + {
+ writer(((GenericRecord)record)[fieldName], encoder);
+ }
+
+ protected override WriteItem ResolveEnum(EnumSchema es)
+ {
+ return (v,e) =>
+ {
+ if( v == null || !(v is GenericEnum) || !((v as \
GenericEnum).Schema.Equals(es))) + throw \
TypeMismatch(v, "enum", "GenericEnum"); + \
e.WriteEnum(es.Ordinal((v as GenericEnum ).Value)); + };
+ }
+
+ protected override void WriteFixed( FixedSchema es, object value, Encoder \
encoder ) + {
+ if (value == null || !(value is GenericFixed) || !(value as \
GenericFixed).Schema.Equals(es)) + {
+ throw TypeMismatch(value, "fixed", "GenericFixed");
+ }
+ GenericFixed ba = (GenericFixed)value;
+ encoder.WriteFixed(ba.Value);
+ }
+
+ /*
+ * FIXME: This method of determining the Union branch has problems. If the \
data is IDictionary<string, object> + * if there are two branches one with \
record schema and the other with map, it choose the first one. Similarly if + \
* the data is byte[] and there are fixed and bytes schemas as branches, it choose the \
first one that matches. + * Also it does not recognize the arrays of \
primitive types. + */
+ protected override bool UnionBranchMatches(Schema sc, object obj)
+ {
+ if (obj == null && sc.Tag != Avro.Schema.Type.Null) return false;
+ switch (sc.Tag)
+ {
+ case Schema.Type.Null:
+ return obj == null;
+ case Schema.Type.Boolean:
+ return obj is bool;
+ case Schema.Type.Int:
+ return obj is int;
+ case Schema.Type.Long:
+ return obj is long;
+ case Schema.Type.Float:
+ return obj is float;
+ case Schema.Type.Double:
+ return obj is double;
+ case Schema.Type.Bytes:
+ return obj is byte[];
+ case Schema.Type.String:
+ return obj is string;
+ case Schema.Type.Error:
+ case Schema.Type.Record:
+ //return obj is GenericRecord && (obj as \
GenericRecord).Schema.Equals(s); + return obj is GenericRecord && \
(obj as GenericRecord).Schema.SchemaName.Equals((sc as RecordSchema).SchemaName); + \
case Schema.Type.Enumeration: + //return obj is GenericEnum && \
(obj as GenericEnum).Schema.Equals(s); + return obj is GenericEnum \
&& (obj as GenericEnum).Schema.SchemaName.Equals((sc as EnumSchema).SchemaName); + \
case Schema.Type.Array: + return obj is Array && !(obj is byte[]);
+ case Schema.Type.Map:
+ return obj is IDictionary<string, object>;
+ case Schema.Type.Union:
+ return false; // Union directly within another union not \
allowed! + case Schema.Type.Fixed:
+ //return obj is GenericFixed && (obj as \
GenericFixed).Schema.Equals(s); + return obj is GenericFixed && \
(obj as GenericFixed).Schema.SchemaName.Equals((sc as FixedSchema).SchemaName); + \
default: + throw new AvroException("Unknown schema type: " + \
sc.Tag); + }
+ }
+
+ private class GenericArrayAccess : ArrayAccess
+ {
+ public void EnsureArrayObject( object value )
+ {
+ if( value == null || !( value is Array ) ) throw TypeMismatch( \
value, "array", "Array" ); + }
+
+ public long GetArrayLength( object value )
+ {
+ return ( (Array) value ).Length;
+ }
+
+ public void WriteArrayValues(object array, WriteItem valueWriter, \
Encoder encoder) + {
+ var arrayInstance = (Array) array;
+ for(int i = 0; i < arrayInstance.Length; i++)
+ {
+ encoder.StartItem();
+ valueWriter(arrayInstance.GetValue(i), encoder);
+ }
+ }
+ }
+ }
+}
Added: avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumReader.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumReader.cs?rev=1540206&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumReader.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumReader.cs Fri Nov \
8 22:15:02 2013 @@ -0,0 +1,596 @@
+ï » ¿/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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.
+ */
+using System.Collections.Generic;
+using System.IO;
+using Avro.IO;
+
+namespace Avro.Generic
+{
+ /// <summary>
+ /// A general purpose reader of data from avro streams. This reader analyzes and \
resolves the reader and writer schemas + /// when constructed so that reads can be \
more efficient. Once constructed, a reader can be reused or shared among threads + \
/// to avoid incurring more resolution costs. + /// </summary>
+ public abstract class PreresolvingDatumReader<T> : DatumReader<T>
+ {
+ public Schema ReaderSchema { get; private set; }
+ public Schema WriterSchema { get; private set; }
+
+ protected delegate object ReadItem(object reuse, Decoder dec);
+
+ // read a specific field from a decoder
+ private delegate object DecoderRead(Decoder dec);
+ // skip specific field(s) from a decoder
+ private delegate void DecoderSkip(Decoder dec);
+ // read & set fields on a record
+ private delegate void FieldReader(object record, Decoder decoder);
+
+ private readonly ReadItem _reader;
+ private readonly Dictionary<SchemaPair,ReadItem> _recordReaders = new \
Dictionary<SchemaPair,ReadItem>(); +
+ protected PreresolvingDatumReader(Schema writerSchema, Schema readerSchema)
+ {
+ ReaderSchema = readerSchema;
+ WriterSchema = writerSchema;
+ if (!ReaderSchema.CanRead(WriterSchema))
+ throw new AvroException("Schema mismatch. Reader: " + ReaderSchema + \
", writer: " + WriterSchema); + _reader = ResolveReader(writerSchema, \
readerSchema); + }
+
+ public T Read(T reuse, Decoder decoder)
+ {
+ return (T)_reader(reuse, decoder);
+ }
+
+ protected abstract ArrayAccess GetArrayAccess(ArraySchema readerSchema);
+ protected abstract EnumAccess GetEnumAccess(EnumSchema readerSchema);
+ protected abstract MapAccess GetMapAccess(MapSchema readerSchema);
+ protected abstract RecordAccess GetRecordAccess(RecordSchema readerSchema);
+ protected abstract FixedAccess GetFixedAccess(FixedSchema readerSchema);
+
+ /// <summary>
+ /// Build a reader that accounts for schema differences between the reader \
and writer schemas. + /// </summary>
+ private ReadItem ResolveReader(Schema writerSchema, Schema readerSchema)
+ {
+ if (readerSchema.Tag == Schema.Type.Union && writerSchema.Tag != \
Schema.Type.Union) + {
+ readerSchema = FindBranch(readerSchema as UnionSchema, \
writerSchema); + }
+ switch (writerSchema.Tag)
+ {
+ case Schema.Type.Null:
+ return ReadNull;
+ case Schema.Type.Boolean:
+ return ReadBoolean;
+ case Schema.Type.Int:
+ {
+ switch (readerSchema.Tag)
+ {
+ case Schema.Type.Long:
+ return Read(d => (long) d.ReadInt());
+ case Schema.Type.Float:
+ return Read(d => (float) d.ReadInt());
+ case Schema.Type.Double:
+ return Read(d => (double) d.ReadInt());
+ default:
+ return Read(d => d.ReadInt());
+ }
+ }
+ case Schema.Type.Long:
+ {
+ switch (readerSchema.Tag)
+ {
+ case Schema.Type.Float:
+ return Read(d => (float) d.ReadLong());
+ case Schema.Type.Double:
+ return Read(d => (double) d.ReadLong());
+ default:
+ return Read(d => d.ReadLong());
+ }
+ }
+ case Schema.Type.Float:
+ {
+ switch (readerSchema.Tag)
+ {
+ case Schema.Type.Double:
+ return Read(d => (double) d.ReadFloat());
+ default:
+ return Read(d => d.ReadFloat());
+ }
+ }
+ case Schema.Type.Double:
+ return Read(d => d.ReadDouble());
+ case Schema.Type.String:
+ return Read(d => d.ReadString());
+ case Schema.Type.Bytes:
+ return Read(d => d.ReadBytes());
+ case Schema.Type.Error:
+ case Schema.Type.Record:
+ return ResolveRecord((RecordSchema)writerSchema, \
(RecordSchema)readerSchema); + case Schema.Type.Enumeration:
+ return ResolveEnum((EnumSchema)writerSchema, \
(EnumSchema)readerSchema); + case Schema.Type.Fixed:
+ return ResolveFixed((FixedSchema)writerSchema, \
(FixedSchema)readerSchema); + case Schema.Type.Array:
+ return ResolveArray((ArraySchema)writerSchema, \
(ArraySchema)readerSchema); + case Schema.Type.Map:
+ return ResolveMap((MapSchema)writerSchema, \
(MapSchema)readerSchema); + case Schema.Type.Union:
+ return ResolveUnion((UnionSchema)writerSchema, readerSchema);
+ default:
+ throw new AvroException("Unknown schema type: " + writerSchema);
+ }
+ }
+
+ private ReadItem ResolveEnum(EnumSchema writerSchema, EnumSchema \
readerSchema) + {
+ var enumAccess = GetEnumAccess(readerSchema);
+
+ if (readerSchema.Equals(writerSchema))
+ {
+ return (r, d) => enumAccess.CreateEnum(r, d.ReadEnum());
+ }
+
+ var translator = new int[writerSchema.Symbols.Count];
+
+ foreach (var symbol in writerSchema.Symbols)
+ {
+ var writerOrdinal = writerSchema.Ordinal(symbol);
+ if (readerSchema.Contains(symbol))
+ {
+ translator[writerOrdinal] = readerSchema.Ordinal(symbol);
+ }
+ else
+ {
+ translator[writerOrdinal] = -1;
+ }
+ }
+
+ return (r, d) =>
+ {
+ var writerOrdinal = d.ReadEnum();
+ var readerOrdinal = translator[writerOrdinal];
+ if (readerOrdinal == -1)
+ {
+ throw new AvroException("No such symbol: " + \
writerSchema[writerOrdinal]); + }
+ return enumAccess.CreateEnum(r, readerOrdinal);
+ };
+ }
+
+ private ReadItem ResolveRecord(RecordSchema writerSchema, RecordSchema \
readerSchema) + {
+ var schemaPair = new SchemaPair(writerSchema, readerSchema);
+ ReadItem recordReader;
+
+ if (_recordReaders.TryGetValue(schemaPair, out recordReader))
+ {
+ return recordReader;
+ }
+
+ FieldReader[] fieldReaderArray = null;
+ var recordAccess = GetRecordAccess(readerSchema);
+
+ recordReader = (r, d) => ReadRecord(r, d, recordAccess, \
fieldReaderArray); + _recordReaders.Add(schemaPair, recordReader);
+
+ var readSteps = new List<FieldReader>();
+
+ foreach (Field wf in writerSchema)
+ {
+ Field rf;
+ if (readerSchema.TryGetFieldAlias(wf.Name, out rf))
+ {
+ var readItem = ResolveReader(wf.Schema, rf.Schema);
+ if(IsReusable(rf.Schema.Tag))
+ {
+ readSteps.Add((rec,d) => recordAccess.AddField(rec, rf.Name, \
rf.Pos, + readItem(recordAccess.GetField(rec, rf.Name, \
rf.Pos), d))); + }
+ else
+ {
+ readSteps.Add((rec, d) => recordAccess.AddField(rec, \
rf.Name, rf.Pos, + readItem(null, d)));
+ }
+ }
+ else
+ {
+ var skip = GetSkip(wf.Schema);
+ readSteps.Add((rec, d) => skip(d));
+ }
+ }
+
+ // fill in defaults for any reader fields not in the writer schema
+ foreach (Field rf in readerSchema)
+ {
+ if (writerSchema.Contains(rf.Name)) continue;
+
+ var defaultStream = new MemoryStream();
+ var defaultEncoder = new BinaryEncoder(defaultStream);
+
+ defaultStream.Position = 0; // reset for writing
+ Resolver.EncodeDefaultValue(defaultEncoder, rf.Schema, \
rf.DefaultValue); + defaultStream.Flush();
+ var defaultBytes = defaultStream.ToArray();
+
+ var readItem = ResolveReader(rf.Schema, rf.Schema);
+
+ var rfInstance = rf;
+ if(IsReusable(rf.Schema.Tag))
+ {
+ readSteps.Add((rec, d) => recordAccess.AddField(rec, \
rfInstance.Name, rfInstance.Pos, + \
readItem(recordAccess.GetField(rec, rfInstance.Name, rfInstance.Pos), + \
new BinaryDecoder(new MemoryStream( defaultBytes))))); + }
+ else
+ {
+ readSteps.Add((rec, d) => recordAccess.AddField(rec, \
rfInstance.Name, rfInstance.Pos, + readItem(null, new \
BinaryDecoder(new MemoryStream(defaultBytes))))); + }
+ }
+
+ fieldReaderArray = readSteps.ToArray();
+ return recordReader;
+ }
+
+ private object ReadRecord(object reuse, Decoder decoder, RecordAccess \
recordAccess, IEnumerable<FieldReader> readSteps ) + {
+ var rec = recordAccess.CreateRecord(reuse);
+ foreach (FieldReader fr in readSteps)
+ {
+ fr(rec, decoder);
+ // TODO: on exception, report offending field
+ }
+ return rec;
+ }
+
+ private ReadItem ResolveUnion(UnionSchema writerSchema, Schema readerSchema)
+ {
+ var lookup = new ReadItem[writerSchema.Count];
+
+ for (int i = 0; i < writerSchema.Count; i++)
+ {
+ var writerBranch = writerSchema[i];
+
+ if (readerSchema is UnionSchema)
+ {
+ var unionReader = (UnionSchema) readerSchema;
+ var readerBranch = unionReader.MatchingBranch(writerBranch);
+ if (readerBranch == -1)
+ {
+ lookup[i] = (r, d) => { throw new AvroException( "No \
matching schema for " + writerBranch + " in " + unionReader ); }; + \
} + else
+ {
+ lookup[i] = ResolveReader(writerBranch, \
unionReader[readerBranch]); + }
+ }
+ else
+ {
+ if (!readerSchema.CanRead(writerBranch))
+ {
+ lookup[i] = (r, d) => { throw new AvroException( "Schema \
mismatch Reader: " + ReaderSchema + ", writer: " + WriterSchema ); }; + \
} + else
+ {
+ lookup[i] = ResolveReader(writerBranch, readerSchema);
+ }
+ }
+ }
+
+ return (r, d) => ReadUnion(r, d, lookup);
+ }
+
+ private object ReadUnion(object reuse, Decoder d, ReadItem[] branchLookup)
+ {
+ return branchLookup[d.ReadUnionIndex()](reuse, d);
+ }
+
+ private ReadItem ResolveMap(MapSchema writerSchema, MapSchema readerSchema)
+ {
+ var rs = readerSchema.ValueSchema;
+ var ws = writerSchema.ValueSchema;
+
+ var reader = ResolveReader(ws, rs);
+ var mapAccess = GetMapAccess(readerSchema);
+
+ return (r,d) => ReadMap(r, d, mapAccess, reader);
+ }
+
+ private object ReadMap(object reuse, Decoder decoder, MapAccess mapAccess, \
ReadItem valueReader) + {
+ object map = mapAccess.Create(reuse);
+
+ for (int n = (int)decoder.ReadMapStart(); n != 0; n = \
(int)decoder.ReadMapNext()) + {
+ mapAccess.AddElements(map, n, valueReader, decoder, false);
+ }
+ return map;
+ }
+
+ private ReadItem ResolveArray(ArraySchema writerSchema, ArraySchema \
readerSchema) + {
+ var itemReader = ResolveReader(writerSchema.ItemSchema, \
readerSchema.ItemSchema); +
+ var arrayAccess = GetArrayAccess(readerSchema);
+ return (r, d) => ReadArray(r, d, arrayAccess, itemReader, \
IsReusable(readerSchema.ItemSchema.Tag)); + }
+
+ private object ReadArray(object reuse, Decoder decoder, ArrayAccess \
arrayAccess, ReadItem itemReader, bool itemReusable) + {
+ object array = arrayAccess.Create(reuse);
+ int i = 0;
+ for (int n = (int)decoder.ReadArrayStart(); n != 0; n = \
(int)decoder.ReadArrayNext()) + {
+ arrayAccess.EnsureSize(ref array, i + n);
+ arrayAccess.AddElements(array, n, i, itemReader, decoder, \
itemReusable); + i += n;
+ }
+ arrayAccess.Resize(ref array, i);
+ return array;
+ }
+
+ private ReadItem ResolveFixed(FixedSchema writerSchema, FixedSchema \
readerSchema) + {
+ if (readerSchema.Size != writerSchema.Size)
+ {
+ throw new AvroException("Size mismatch between reader and writer \
fixed schemas. Writer: " + writerSchema + + ", reader: " + \
readerSchema); + }
+ var fixedAccess = GetFixedAccess(readerSchema);
+ return (r, d) => ReadFixed(r, d, fixedAccess);
+ }
+
+ private object ReadFixed(object reuse, Decoder decoder, FixedAccess \
fixedAccess) + {
+ var fixedrec = fixedAccess.CreateFixed(reuse);
+ decoder.ReadFixed(fixedAccess.GetFixedBuffer(fixedrec));
+ return fixedrec;
+ }
+
+ protected static Schema FindBranch(UnionSchema us, Schema s)
+ {
+ int index = us.MatchingBranch(s);
+ if (index >= 0) return us[index];
+ throw new AvroException("No matching schema for " + s + " in " + us);
+ }
+
+ private object ReadNull(object reuse, Decoder decoder)
+ {
+ decoder.ReadNull();
+ return null;
+ }
+
+ private object ReadBoolean(object reuse, Decoder decoder)
+ {
+ return decoder.ReadBoolean();
+ }
+
+ private ReadItem Read(DecoderRead decoderRead)
+ {
+ return (r, d) => decoderRead(d);
+ }
+
+ private DecoderSkip GetSkip(Schema writerSchema)
+ {
+ switch (writerSchema.Tag)
+ {
+ case Schema.Type.Null:
+ return d => d.SkipNull();
+ case Schema.Type.Boolean:
+ return d => d.SkipBoolean();
+ case Schema.Type.Int:
+ return d => d.SkipInt();
+ case Schema.Type.Long:
+ return d => d.SkipLong();
+ case Schema.Type.Float:
+ return d => d.SkipFloat();
+ case Schema.Type.Double:
+ return d => d.SkipDouble();
+ case Schema.Type.String:
+ return d => d.SkipString();
+ case Schema.Type.Bytes:
+ return d => d.SkipBytes();
+ case Schema.Type.Error:
+ case Schema.Type.Record:
+ var recordSkips = new List<DecoderSkip>();
+ var recSchema = (RecordSchema)writerSchema;
+ recSchema.Fields.ForEach(r => \
recordSkips.Add(GetSkip(r.Schema))); + return d => \
recordSkips.ForEach(s=>s(d)); + case Schema.Type.Enumeration:
+ return d => d.SkipEnum();
+ case Schema.Type.Fixed:
+ var size = ((FixedSchema)writerSchema).Size;
+ return d => d.SkipFixed(size);
+ case Schema.Type.Array:
+ var itemSkip = GetSkip(((ArraySchema)writerSchema).ItemSchema);
+ return d =>
+ {
+ for (long n = d.ReadArrayStart(); n != 0; n = \
d.ReadArrayNext()) + {
+ for (long i = 0; i < n; i++) itemSkip(d);
+ }
+ };
+ case Schema.Type.Map:
+ {
+ var valueSkip = \
GetSkip(((MapSchema)writerSchema).ValueSchema); + return d =>
+ {
+ for (long n = d.ReadMapStart(); n != 0; n = \
d.ReadMapNext()) + {
+ for (long i = 0; i < n; i++) { d.SkipString(); \
valueSkip(d); } + }
+ };
+ }
+ case Schema.Type.Union:
+ var unionSchema = (UnionSchema)writerSchema;
+ var lookup = new DecoderSkip[unionSchema.Count];
+ for (int i = 0; i < unionSchema.Count; i++)
+ {
+ lookup[i] = GetSkip( unionSchema[i] );
+ }
+ return d => lookup[d.ReadUnionIndex()](d);
+ default:
+ throw new AvroException("Unknown schema type: " + writerSchema);
+ }
+ }
+
+ /// <summary>
+ /// Indicates if it's possible to reuse an object of the specified type. \
Generally + /// false for immutable objects like int, long, string, etc but \
may differ between + /// the Specific and Generic implementations. Used to \
avoid retrieving the existing + /// value if it's not reusable.
+ /// </summary>
+ protected virtual bool IsReusable(Schema.Type tag)
+ {
+ return true;
+ }
+
+ // interfaces to handle details of working with Specific vs Generic objects
+
+ protected interface RecordAccess
+ {
+ /// <summary>
+ /// Creates a new record object. Derived classes can override this to \
return an object of their choice. + /// </summary>
+ /// <param name="reuse">If appropriate, will reuse this object instead \
of constructing a new one</param> + /// <returns></returns>
+ object CreateRecord(object reuse);
+
+ /// <summary>
+ /// Used by the default implementation of ReadRecord() to get the \
existing field of a record object. The derived + /// classes can override \
this to make their own interpretation of the record object. + /// \
</summary> + /// <param name="record">The record object to be probed into. \
This is guaranteed to be one that was returned + /// by a previous call to \
CreateRecord.</param> + /// <param name="fieldName">The name of the field \
to probe.</param> + /// <param name="fieldPos">field number</param>
+ /// <returns>The value of the field, if found. Null otherwise.</returns>
+ object GetField(object record, string fieldName, int fieldPos);
+
+ /// <summary>
+ /// Used by the default implementation of ReadRecord() to add a field to \
a record object. The derived + /// classes can override this to suit their \
own implementation of the record object. + /// </summary>
+ /// <param name="record">The record object to be probed into. This is \
guaranteed to be one that was returned + /// by a previous call to \
CreateRecord.</param> + /// <param name="fieldName">The name of the field \
to probe.</param> + /// <param name="fieldPos">field number</param>
+ /// <param name="fieldValue">The value to be added for the field</param>
+ void AddField(object record, string fieldName, int fieldPos, object \
fieldValue); + }
+
+ protected interface EnumAccess
+ {
+ object CreateEnum(object reuse, int ordinal);
+ }
+
+ protected interface FixedAccess
+ {
+ /// <summary>
+ /// Returns a fixed object.
+ /// </summary>
+ /// <param name="reuse">If appropriate, uses this object instead of \
creating a new one.</param> + /// <returns>A fixed object with an \
appropriate buffer.</returns> + object CreateFixed(object reuse);
+
+ /// <summary>
+ /// Returns a buffer of appropriate size to read data into.
+ /// </summary>
+ /// <param name="f">The fixed object. It is guaranteed that this is \
something that has been previously + /// returned by CreateFixed</param>
+ /// <returns>A byte buffer of fixed's size.</returns>
+ byte[] GetFixedBuffer(object f);
+ }
+
+ protected interface ArrayAccess
+ {
+ /// <summary>
+ /// Creates a new array object. The initial size of the object could be \
anything. + /// </summary>
+ /// <param name="reuse">If appropriate use this instead of creating a \
new one.</param> + /// <returns>An object suitable to deserialize an avro \
array</returns> + object Create(object reuse);
+
+ /// <summary>
+ /// Hint that the array should be able to handle at least targetSize \
elements. The array + /// is not required to be resized
+ /// </summary>
+ /// <param name="array">Array object who needs to support targetSize \
elements. This is guaranteed to be somthing returned by + /// a previous \
call to CreateArray().</param> + /// <param name="targetSize">The new \
size.</param> + void EnsureSize(ref object array, int targetSize);
+
+ /// <summary>
+ /// Resizes the array to the new value.
+ /// </summary>
+ /// <param name="array">Array object whose size is required. This is \
guaranteed to be somthing returned by + /// a previous call to \
CreateArray().</param> + /// <param name="targetSize">The new \
size.</param> + void Resize(ref object array, int targetSize);
+
+ void AddElements( object array, int elements, int index, ReadItem \
itemReader, Decoder decoder, bool reuse ); + }
+
+ protected interface MapAccess
+ {
+ /// <summary>
+ /// Creates a new map object.
+ /// </summary>
+ /// <param name="reuse">If appropriate, use this map object instead of \
creating a new one.</param> + /// <returns>An empty map object.</returns>
+ object Create(object reuse);
+
+ void AddElements(object map, int elements, ReadItem itemReader, Decoder \
decoder, bool reuse); + }
+
+ private class SchemaPair
+ {
+ private Schema _writerSchema;
+ private Schema _readerSchema;
+
+ public SchemaPair( Schema writerSchema, Schema readerSchema )
+ {
+ _writerSchema = writerSchema;
+ _readerSchema = readerSchema;
+ }
+
+ protected bool Equals( SchemaPair other )
+ {
+ return Equals( _writerSchema, other._writerSchema ) && Equals( \
_readerSchema, other._readerSchema ); + }
+
+ public override bool Equals( object obj )
+ {
+ if( ReferenceEquals( null, obj ) ) return false;
+ if( ReferenceEquals( this, obj ) ) return true;
+ if( obj.GetType() != this.GetType() ) return false;
+ return Equals( (SchemaPair) obj );
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return ( ( _writerSchema != null ? _writerSchema.GetHashCode() : \
0 ) * 397 ) ^ ( _readerSchema != null ? _readerSchema.GetHashCode() : 0 ); + \
} + }
+ }
+ }
+}
Added: avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumWriter.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumWriter.cs?rev=1540206&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumWriter.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Generic/PreresolvingDatumWriter.cs Fri Nov \
8 22:15:02 2013 @@ -0,0 +1,375 @@
+ï » ¿/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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.
+ */
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using Encoder = Avro.IO.Encoder;
+
+namespace Avro.Generic
+{
+ /// <summary>
+ /// A general purpose writer of data from avro streams. This writer analyzes the \
writer schema + /// when constructed so that writes can be more efficient. Once \
constructed, a writer can be reused or shared among threads + /// to avoid \
incurring more resolution costs. + /// </summary>
+ public abstract class PreresolvingDatumWriter<T> : DatumWriter<T>
+ {
+ public Schema Schema { get; private set; }
+
+ protected delegate void WriteItem(Object value, Encoder encoder);
+
+ private readonly WriteItem _writer;
+ private readonly ArrayAccess _arrayAccess;
+ private readonly MapAccess _mapAccess;
+
+ private readonly Dictionary<RecordSchema,WriteItem> _recordWriters = new \
Dictionary<RecordSchema,WriteItem>(); +
+ public void Write(T datum, Encoder encoder)
+ {
+ _writer( datum, encoder );
+ }
+
+ protected PreresolvingDatumWriter(Schema schema, ArrayAccess arrayAccess, \
MapAccess mapAccess) + {
+ Schema = schema;
+ _arrayAccess = arrayAccess;
+ _mapAccess = mapAccess;
+ _writer = ResolveWriter(schema);
+ }
+
+ private WriteItem ResolveWriter( Schema schema )
+ {
+ switch (schema.Tag)
+ {
+ case Schema.Type.Null:
+ return WriteNull;
+ case Schema.Type.Boolean:
+ return (v, e) => Write<bool>( v, schema.Tag, e.WriteBoolean );
+ case Schema.Type.Int:
+ return (v, e) => Write<int>( v, schema.Tag, e.WriteInt );
+ case Schema.Type.Long:
+ return (v, e) => Write<long>( v, schema.Tag, e.WriteLong );
+ case Schema.Type.Float:
+ return (v, e) => Write<float>( v, schema.Tag, e.WriteFloat );
+ case Schema.Type.Double:
+ return (v, e) => Write<double>( v, schema.Tag, e.WriteDouble );
+ case Schema.Type.String:
+ return (v, e) => Write<string>( v, schema.Tag, e.WriteString );
+ case Schema.Type.Bytes:
+ return (v, e) => Write<byte[]>( v, schema.Tag, e.WriteBytes );
+ case Schema.Type.Error:
+ case Schema.Type.Record:
+ return ResolveRecord((RecordSchema) schema);
+ case Schema.Type.Enumeration:
+ return ResolveEnum(schema as EnumSchema);
+ case Schema.Type.Fixed:
+ return (v, e) => WriteFixed(schema as FixedSchema, v, e);
+ case Schema.Type.Array:
+ return ResolveArray((ArraySchema)schema);
+ case Schema.Type.Map:
+ return ResolveMap((MapSchema)schema);
+ case Schema.Type.Union:
+ return ResolveUnion((UnionSchema)schema);
+ default:
+ return (v, e) => error(schema, v);
+ }
+ }
+
+ /// <summary>
+ /// Serializes a "null"
+ /// </summary>
+ /// <param name="value">The object to be serialized using null \
schema</param> + /// <param name="encoder">The encoder to use while \
serialization</param> + protected void WriteNull(object value, Encoder \
encoder) + {
+ if (value != null) throw TypeMismatch(value, "null", "null");
+ }
+
+ /// <summary>
+ /// A generic method to serialize primitive Avro types.
+ /// </summary>
+ /// <typeparam name="S">Type of the C# type to be serialized</typeparam>
+ /// <param name="value">The value to be serialized</param>
+ /// <param name="tag">The schema type tag</param>
+ /// <param name="writer">The writer which should be used to write the given \
type.</param> + protected void Write<S>(object value, Schema.Type tag, \
Writer<S> writer) + {
+ if (!(value is S)) throw TypeMismatch(value, tag.ToString(), \
typeof(S).ToString()); + writer((S)value);
+ }
+
+
+ /// <summary>
+ /// Serialized a record using the given RecordSchema. It uses GetField \
method + /// to extract the field value from the given object.
+ /// </summary>
+ /// <param name="schema">The RecordSchema to use for serialization</param>
+ private WriteItem ResolveRecord(RecordSchema recordSchema)
+ {
+ WriteItem recordResolver;
+ if (_recordWriters.TryGetValue(recordSchema, out recordResolver))
+ {
+ return recordResolver;
+ }
+ var writeSteps = new RecordFieldWriter[recordSchema.Fields.Count];
+ recordResolver = (v, e) => WriteRecordFields(v, writeSteps, e);
+
+ _recordWriters.Add(recordSchema, recordResolver);
+
+ int index = 0;
+ foreach (Field field in recordSchema)
+ {
+ var record = new RecordFieldWriter
+ {
+ WriteField = ResolveWriter(field.Schema),
+ Field = field
+ };
+ writeSteps[index++] = record;
+ }
+
+ return recordResolver;
+ }
+
+ protected abstract void WriteRecordFields(object record, RecordFieldWriter[] \
writers, Encoder encoder); +
+
+ protected class RecordFieldWriter
+ {
+ public WriteItem WriteField { get; set; }
+ public Field Field { get; set; }
+ }
+
+ protected abstract void EnsureRecordObject(RecordSchema recordSchema, object \
value); +
+ /// <summary>
+ /// Extracts the field value from the given object.
+ /// </summary>
+ /// <param name="value">The record value from which the field needs to be \
extracted</param> + /// <param name="fieldName">The name of the field in the \
record</param> + /// <param name="fieldPos">The position of field in the \
record</param> + /// <returns></returns>
+ protected abstract void WriteField(object record, string fieldName, int \
fieldPos, WriteItem writer, Encoder encoder ); +
+ /// <summary>
+ /// Serializes an enumeration.
+ /// </summary>
+ /// <param name="es">The EnumSchema for serialization</param>
+ protected abstract WriteItem ResolveEnum(EnumSchema es);
+
+ /// <summary>
+ /// Serialized an array. The default implementation calls \
EnsureArrayObject() to ascertain that the + /// given value is an array. It \
then calls GetArrayLength() and GetArrayElement() + /// to access the members \
of the array and then serialize them. + /// </summary>
+ /// <param name="schema">The ArraySchema for serialization</param>
+ /// <param name="value">The value being serialized</param>
+ /// <param name="encoder">The encoder for serialization</param>
+ protected WriteItem ResolveArray(ArraySchema schema)
+ {
+ var itemWriter = ResolveWriter(schema.ItemSchema);
+ return (d,e) => WriteArray(itemWriter, d, e);
+ }
+
+ private void WriteArray(WriteItem itemWriter, object array, Encoder encoder)
+ {
+ _arrayAccess.EnsureArrayObject(array);
+ long l = _arrayAccess.GetArrayLength(array);
+ encoder.WriteArrayStart();
+ encoder.SetItemCount(l);
+ _arrayAccess.WriteArrayValues(array, itemWriter, encoder);
+ encoder.WriteArrayEnd();
+ }
+
+ private WriteItem ResolveMap(MapSchema mapSchema)
+ {
+ var itemWriter = ResolveWriter(mapSchema.ValueSchema);
+ return (v, e) => WriteMap(itemWriter, v, e);
+ }
+
+ /// <summary>
+ /// Serialized a map. The default implementation first ensure that the value \
is indeed a map and then uses + /// GetMapSize() and GetMapElements() to \
access the contents of the map. + /// </summary>
+ /// <param name="schema">The MapSchema for serialization</param>
+ /// <param name="value">The value to be serialized</param>
+ /// <param name="encoder">The encoder for serialization</param>
+ protected void WriteMap(WriteItem itemWriter, object value, Encoder encoder)
+ {
+ _mapAccess.EnsureMapObject(value);
+ encoder.WriteMapStart();
+ encoder.SetItemCount(_mapAccess.GetMapSize(value));
+ _mapAccess.WriteMapValues(value, itemWriter, encoder);
+ encoder.WriteMapEnd();
+ }
+
+
+ private WriteItem ResolveUnion(UnionSchema unionSchema)
+ {
+ var branchSchemas = unionSchema.Schemas.ToArray();
+ var branchWriters = new WriteItem[branchSchemas.Length];
+ int branchIndex = 0;
+ foreach (var branch in branchSchemas)
+ {
+ branchWriters[branchIndex++] = ResolveWriter(branch);
+ }
+
+
+ return (v, e) => WriteUnion(unionSchema, branchSchemas, branchWriters, \
v, e); + }
+
+ /// <summary>
+ /// Resolves the given value against the given UnionSchema and serializes \
the object against + /// the resolved schema member.
+ /// </summary>
+ /// <param name="us">The UnionSchema to resolve against</param>
+ /// <param name="value">The value to be serialized</param>
+ /// <param name="encoder">The encoder for serialization</param>
+ private void WriteUnion(UnionSchema unionSchema, Schema[] branchSchemas, \
WriteItem[] branchWriters, object value, Encoder encoder) + {
+ int index = ResolveUnion(unionSchema, branchSchemas, value);
+ encoder.WriteUnionIndex(index);
+ branchWriters[index](value, encoder);
+ }
+
+ /// <summary>
+ /// Finds the branch within the given UnionSchema that matches the given \
object. The default implementation + /// calls Matches() method in the order \
of branches within the UnionSchema. If nothing matches, throws + /// an \
exception. + /// </summary>
+ /// <param name="us">The UnionSchema to resolve against</param>
+ /// <param name="obj">The object that should be used in matching</param>
+ /// <returns></returns>
+ protected int ResolveUnion(UnionSchema us, Schema[] branchSchemas, object \
obj) + {
+ for (int i = 0; i < branchSchemas.Length; i++)
+ {
+ if (UnionBranchMatches(branchSchemas[i], obj)) return i;
+ }
+ throw new AvroException("Cannot find a match for " + obj.GetType() + " \
in " + us); + }
+
+ /// <summary>
+ /// Serialized a fixed object. The default implementation requires that the \
value is + /// a GenericFixed object with an identical schema as es.
+ /// </summary>
+ /// <param name="es">The schema for serialization</param>
+ /// <param name="value">The value to be serialized</param>
+ /// <param name="encoder">The encoder for serialization</param>
+ protected abstract void WriteFixed(FixedSchema es, object value, Encoder \
encoder); +
+ protected static AvroException TypeMismatch(object obj, string schemaType, \
string type) + {
+ return new AvroException(type + " required to write against " + \
schemaType + " schema but found " + (null == obj ? "null" : obj.GetType().ToString()) \
); + }
+
+ private void error(Schema schema, Object value)
+ {
+ throw new AvroTypeException("Not a " + schema + ": " + value);
+ }
+
+ protected abstract bool UnionBranchMatches(Schema sc, object obj);
+
+ protected interface EnumAccess
+ {
+ void WriteEnum(object value);
+ }
+
+ protected interface ArrayAccess
+ {
+ /// <summary>
+ /// Checks if the given object is an array. If it is a valid array, this \
function returns normally. Otherwise, + /// it throws an exception. The \
default implementation checks if the value is an array. + /// </summary>
+ /// <param name="value"></param>
+ void EnsureArrayObject(object value);
+
+ /// <summary>
+ /// Returns the length of an array. The default implementation requires \
the object + /// to be an array of objects and returns its length. The \
defaul implementation + /// gurantees that EnsureArrayObject() has been \
called on the value before this + /// function is called.
+ /// </summary>
+ /// <param name="value">The object whose array length is \
required</param> + /// <returns>The array length of the given \
object</returns> + long GetArrayLength(object value);
+
+ /// <summary>
+ /// Returns the element at the given index from the given array object. \
The default implementation + /// requires that the value is an object \
array and returns the element in that array. The defaul implementation + \
/// gurantees that EnsureArrayObject() has been called on the value before this + \
/// function is called. + /// </summary>
+ /// <param name="value">The array object</param>
+ /// <param name="index">The index to look for</param>
+ /// <returns>The array element at the index</returns>
+ void WriteArrayValues(object array, WriteItem valueWriter, Encoder \
encoder); + }
+
+ protected interface MapAccess
+ {
+ /// <summary>
+ /// Checks if the given object is a map. If it is a valid map, this \
function returns normally. Otherwise, + /// it throws an exception. The \
default implementation checks if the value is an IDictionary<string, object>. + \
/// </summary> + /// <param name="value"></param>
+ void EnsureMapObject(object value);
+
+ /// <summary>
+ /// Returns the size of the map object. The default implementation \
gurantees that EnsureMapObject has been + /// successfully called with the \
given value. The default implementation requires the value + /// to be an \
IDictionary<string, object> and returns the number of elements in it. + \
/// </summary> + /// <param name="value">The map object whose size is \
desired</param> + /// <returns>The size of the given map object</returns>
+ long GetMapSize(object value);
+
+ /// <summary>
+ /// Returns the contents of the given map object. The default \
implementation guarantees that EnsureMapObject + /// has been called with \
the given value. The defualt implementation of this method requires that + \
/// the value is an IDictionary<string, object> and returns its contents. + \
/// </summary> + /// <param name="value">The map object whose size is \
desired</param> + /// <returns>The contents of the given map \
object</returns> + void WriteMapValues(object map, WriteItem valueWriter, \
Encoder encoder); + }
+
+ protected class DictionaryMapAccess : MapAccess
+ {
+ public void EnsureMapObject( object value )
+ {
+ if( value == null || !( value is IDictionary ) ) throw TypeMismatch( \
value, "map", "IDictionary" ); + }
+
+ public long GetMapSize( object value )
+ {
+ return ( (IDictionary) value ).Count;
+ }
+
+ public void WriteMapValues(object map, WriteItem valueWriter, Encoder \
encoder) + {
+ foreach (DictionaryEntry entry in ((IDictionary)map))
+ {
+ encoder.StartItem();
+ encoder.WriteString(entry.Key.ToString());
+ valueWriter(entry.Value, encoder);
+ }
+ }
+ }
+ }
+}
Added: avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumReader.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumReader.cs?rev=1540206&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumReader.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumReader.cs Fri Nov 8 \
22:15:02 2013 @@ -0,0 +1,232 @@
+ï » ¿/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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.
+ */
+using System.Collections;
+using Avro.Generic;
+using Avro.IO;
+
+namespace Avro.Specific
+{
+ /// PreresolvingDatumReader for reading data to ISpecificRecord classes.
+ /// <see cref="PreresolvingDatumReader{T}">For more information about \
performance considerations for choosing this implementation</see> + public class \
SpecificDatumReader<T> : PreresolvingDatumReader<T> + {
+ public SpecificDatumReader(Schema writerSchema, Schema readerSchema) : \
base(writerSchema, readerSchema) + {
+ }
+
+ protected override bool IsReusable(Schema.Type tag)
+ {
+ switch (tag)
+ {
+ case Schema.Type.Double:
+ case Schema.Type.Boolean:
+ case Schema.Type.Int:
+ case Schema.Type.Long:
+ case Schema.Type.Float:
+ case Schema.Type.Bytes:
+ case Schema.Type.Enumeration:
+ case Schema.Type.String:
+ case Schema.Type.Null:
+ return false;
+ }
+ return true;
+ }
+
+ protected override ArrayAccess GetArrayAccess(ArraySchema readerSchema)
+ {
+ return new SpecificArrayAccess(readerSchema);
+ }
+
+ protected override EnumAccess GetEnumAccess(EnumSchema readerSchema)
+ {
+ return new SpecificEnumAccess();
+ }
+
+ protected override MapAccess GetMapAccess(MapSchema readerSchema)
+ {
+ return new SpecificMapAccess(readerSchema);
+ }
+
+ protected override RecordAccess GetRecordAccess(RecordSchema readerSchema)
+ {
+ if (readerSchema.Name == null)
+ {
+ // ipc support
+ return new GenericDatumReader<T>.GenericRecordAccess(readerSchema);
+ }
+ return new SpecificRecordAccess(readerSchema);
+ }
+
+ protected override FixedAccess GetFixedAccess(FixedSchema readerSchema)
+ {
+ return new SpecificFixedAccess(readerSchema);
+ }
+
+ private static ObjectCreator.CtorDelegate GetConstructor(string name, \
Schema.Type schemaType) + {
+ var creator = ObjectCreator.Instance;
+ return creator.GetConstructor(name, schemaType, creator.GetType(name, \
schemaType)); + }
+
+ private class SpecificEnumAccess : EnumAccess
+ {
+ public object CreateEnum(object reuse, int ordinal)
+ {
+ return ordinal;
+ }
+ }
+
+ private class SpecificRecordAccess : RecordAccess
+ {
+ private ObjectCreator.CtorDelegate objCreator;
+
+ public SpecificRecordAccess(RecordSchema readerSchema)
+ {
+ objCreator = GetConstructor(readerSchema.Fullname, \
Schema.Type.Record); + }
+
+ public object CreateRecord(object reuse)
+ {
+ return reuse ?? objCreator();
+ }
+
+ public object GetField(object record, string fieldName, int fieldPos)
+ {
+ return ((ISpecificRecord)record).Get(fieldPos);
+ }
+
+ public void AddField(object record, string fieldName, int fieldPos, \
object fieldValue) + {
+ ((ISpecificRecord)record).Put(fieldPos, fieldValue);
+ }
+ }
+
+ private class SpecificFixedAccess : FixedAccess
+ {
+ private ObjectCreator.CtorDelegate objCreator;
+
+ public SpecificFixedAccess(FixedSchema readerSchema)
+ {
+ objCreator = GetConstructor(readerSchema.Fullname, \
Schema.Type.Fixed); + }
+
+ public object CreateFixed(object reuse)
+ {
+ return reuse ?? objCreator();
+ }
+
+ public byte[] GetFixedBuffer(object rec)
+ {
+ return ((SpecificFixed) rec).Value;
+ }
+ }
+
+ private class SpecificArrayAccess : ArrayAccess
+ {
+ private ObjectCreator.CtorDelegate objCreator;
+
+ public SpecificArrayAccess(ArraySchema readerSchema)
+ {
+ bool nEnum = false;
+ string type = Avro.CodeGen.getType(readerSchema, false, ref nEnum);
+ type = type.Remove(0, 6); // remove IList<
+ type = type.Remove(type.Length - 1); // remove >
+
+ objCreator = GetConstructor(type, Schema.Type.Array);
+ }
+
+ public object Create(object reuse)
+ {
+ IList array;
+
+ if( reuse != null )
+ {
+ array = reuse as IList;
+ if( array == null )
+ throw new AvroException( "array object does not implement \
non-generic IList" ); + // retaining existing behavior where array \
contents aren't reused + // TODO: try to reuse contents?
+ array.Clear();
+ }
+ else
+ array = objCreator() as IList;
+ return array;
+ }
+
+ public void EnsureSize(ref object array, int targetSize)
+ {
+ // no action needed
+ }
+
+ public void Resize(ref object array, int targetSize)
+ {
+ // no action needed
+ }
+
+ public void AddElements( object array, int elements, int index, ReadItem \
itemReader, Decoder decoder, bool reuse ) + {
+ var list = (IList)array;
+ for (int i=0; i < elements; i++)
+ {
+ list.Add( itemReader( null, decoder ) );
+ }
+ }
+ }
+
+ private class SpecificMapAccess : MapAccess
+ {
+ private ObjectCreator.CtorDelegate objCreator;
+
+ public SpecificMapAccess(MapSchema readerSchema)
+ {
+ bool nEnum = false;
+ string type = Avro.CodeGen.getType(readerSchema, false, ref nEnum);
+ type = type.Remove(0, 19); // remove IDictionary<string,
+ type = type.Remove(type.Length - 1); // remove >
+
+ objCreator = GetConstructor(type, Schema.Type.Map);
+ }
+
+ public object Create(object reuse)
+ {
+ IDictionary map;
+ if (reuse != null)
+ {
+ map = reuse as IDictionary;
+ if (map == null)
+ throw new AvroException("map object does not implement \
non-generic IList"); +
+ map.Clear();
+ }
+ else
+ map = objCreator() as System.Collections.IDictionary;
+ return map;
+ }
+
+ public void AddElements(object mapObj, int elements, ReadItem \
itemReader, Decoder decoder, bool reuse) + {
+ var map = ((IDictionary)mapObj);
+ for (int i = 0; i < elements; i++)
+ {
+ var key = decoder.ReadString();
+ map[key] = itemReader(null, decoder);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
Added: avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumWriter.cs
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumWriter.cs?rev=1540206&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumWriter.cs (added)
+++ avro/trunk/lang/csharp/src/apache/main/Specific/SpecificDatumWriter.cs Fri Nov 8 \
22:15:02 2013 @@ -0,0 +1,172 @@
+ï » ¿/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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.
+ */
+using System;
+using System.Collections;
+using Avro.Generic;
+using Encoder = Avro.IO.Encoder;
+
+namespace Avro.Specific
+{
+ /// <summary>
+ /// PreresolvingDatumWriter for writing data from ISpecificRecord classes.
+ /// <see cref="PreresolvingDatumWriter{T}">For more information about \
performance considerations for choosing this implementation</see> + /// </summary>
+ public class SpecificDatumWriter<T> : PreresolvingDatumWriter<T>
+ {
+ public SpecificDatumWriter(Schema schema) : base(schema, new \
SpecificArrayAccess(), new DictionaryMapAccess()) + {
+ }
+
+ protected override void WriteRecordFields(object recordObj, \
RecordFieldWriter[] writers, Encoder encoder) + {
+ var record = (ISpecificRecord) recordObj;
+ for (int i = 0; i < writers.Length; i++)
+ {
+ var writer = writers[i];
+ writer.WriteField(record.Get(writer.Field.Pos), encoder);
+ }
+ }
+
+ protected override void EnsureRecordObject(RecordSchema recordSchema, object \
value) + {
+ if (!(value is ISpecificRecord))
+ throw new AvroTypeException("Record object is not derived from \
ISpecificRecord"); + }
+
+ protected override void WriteField(object record, string fieldName, int \
fieldPos, WriteItem writer, Encoder encoder) + {
+ writer(((ISpecificRecord)record).Get(fieldPos), encoder);
+ }
+
+ protected override WriteItem ResolveEnum(EnumSchema es)
+ {
+ var type = ObjectCreator.Instance.GetType(es);
+
+ var enumNames = Enum.GetNames(type);
+ var translator = new int[enumNames.Length];
+ for(int i = 0; i < enumNames.Length; i++)
+ {
+ if(es.Contains(enumNames[i]))
+ {
+ translator[i] = es.Ordinal(enumNames[i]);
+ }
+ else
+ {
+ translator[i] = -1;
+ }
+ }
+
+ return (v,e) =>
+ {
+ if(v == null)
+ throw new AvroTypeException("value is null in \
SpecificDefaultWriter.WriteEnum"); + if(v.GetType() == \
type) + {
+ int translated = translator[(int)v];
+ if (translated == -1)
+ {
+ throw new AvroTypeException("Unknown enum value:" \
+ v.ToString()); + }
+ else
+ {
+ e.WriteEnum(translated);
+ }
+ }
+ else
+ {
+ e.WriteEnum(es.Ordinal(v.ToString()));
+ }
+ };
+ }
+
+ protected override void WriteFixed(FixedSchema schema, object value, Encoder \
encoder) + {
+ var fixedrec = value as SpecificFixed;
+ if (fixedrec == null)
+ throw new AvroTypeException("Fixed object is not derived from \
SpecificFixed"); +
+ encoder.WriteFixed(fixedrec.Value);
+ }
+
+ protected override bool UnionBranchMatches( Schema sc, object obj )
+ {
+ if (obj == null && sc.Tag != Avro.Schema.Type.Null) return false;
+ switch (sc.Tag)
+ {
+ case Schema.Type.Null:
+ return obj == null;
+ case Schema.Type.Boolean:
+ return obj is bool;
+ case Schema.Type.Int:
+ return obj is int;
+ case Schema.Type.Long:
+ return obj is long;
+ case Schema.Type.Float:
+ return obj is float;
+ case Schema.Type.Double:
+ return obj is double;
+ case Schema.Type.Bytes:
+ return obj is byte[];
+ case Schema.Type.String:
+ return obj is string;
+ case Schema.Type.Error:
+ case Schema.Type.Record:
+ return obj is ISpecificRecord &&
+ (((obj as ISpecificRecord).Schema) as \
RecordSchema).SchemaName.Equals((sc as RecordSchema).SchemaName); + \
case Schema.Type.Enumeration: + return obj.GetType().IsEnum && (sc \
as EnumSchema).Symbols.Contains(obj.ToString()); + case \
Schema.Type.Array: + return obj is System.Collections.IList;
+ case Schema.Type.Map:
+ return obj is System.Collections.IDictionary;
+ case Schema.Type.Union:
+ return false; // Union directly within another union not \
allowed! + case Schema.Type.Fixed:
+ return obj is SpecificFixed &&
+ (((obj as SpecificFixed).Schema) as \
FixedSchema).SchemaName.Equals((sc as FixedSchema).SchemaName); + \
default: + throw new AvroException("Unknown schema type: " + \
sc.Tag); + }
+ }
+
+ class SpecificArrayAccess : ArrayAccess
+ {
+ public void EnsureArrayObject( object value )
+ {
+ if( !( value is System.Collections.IList ) )
+ {
+ throw new AvroTypeException( "Array does not implement \
non-generic IList" ); + }
+ }
+
+ public long GetArrayLength(object value)
+ {
+ return ((IList)value).Count;
+ }
+
+ public void WriteArrayValues(object array, WriteItem valueWriter, \
Encoder encoder) + {
+ var list = (IList) array;
+ for (int i = 0; i < list.Count; i++ )
+ {
+ valueWriter(list[i], encoder);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
Added: avro/trunk/lang/csharp/src/apache/perf/Avro.perf.csproj
URL: http://svn.apache.org/viewvc/avro/trunk/lang/csharp/src/apache/perf/Avro.perf.csproj?rev=1540206&view=auto
==============================================================================
--- avro/trunk/lang/csharp/src/apache/perf/Avro.perf.csproj (added)
+++ avro/trunk/lang/csharp/src/apache/perf/Avro.perf.csproj Fri Nov 8 22:15:02 2013
@@ -0,0 +1,141 @@
+ï » ¿<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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
+
+ http://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.
+-->
+<Project ToolsVersion="4.0" DefaultTargets="Build" \
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{AC4E1909-2594-4D01-9B2B-B832C07BAFE5}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Avro.perf</RootNamespace>
+ <AssemblyName>Avro.perf</AssemblyName>
+ <TargetFrameworkVersion Condition=" '$(TargetFrameworkVersion)' == '' \
">v4.0</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <UpgradeBackupLocation />
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\..\build\perf\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\..\build\perf\Release\</OutputPath>
+ <DefineConstants>
+ </DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+ </PropertyGroup>
+ <PropertyGroup>
+ <StartupObject />
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Castle.Core, Version=3.2.0.0, Culture=neutral, \
PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL"> + \
<SpecificVersion>False</SpecificVersion> + \
<HintPath>..\..\..\..\..\lang\csharp\lib\main\Castle.Core.dll</HintPath> + \
</Reference> + <Reference Include="nunit.framework, Version=2.5.7.10213, \
Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL"> + \
<SpecificVersion>False</SpecificVersion> + \
<HintPath>..\..\..\lib\test\nunit.framework.dll</HintPath> + </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\ipc\Avro.ipc.csproj">
+ <Project>{3b05043a-dc6c-49b6-85bf-9ab055d0b414}</Project>
+ <Name>Avro.ipc</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\main\Avro.main.csproj">
+ <Project>{A0A5CA3C-F58C-4D07-98B0-2C7B62AB20F0}</Project>
+ <Name>Avro.main</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include=".NETFramework,Version=v3.5">
+ <Visible>False</Visible>
+ <ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+ <Visible>False</Visible>
+ <ProductName>Windows Installer 3.1</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="com\foo\A.cs" />
+ <Compile Include="com\foo\Complex.cs" />
+ <Compile Include="com\foo\MyEnum.cs" />
+ <Compile Include="com\foo\MyFixed.cs" />
+ <Compile Include="com\foo\Narrow.cs" />
+ <Compile Include="com\foo\newRec.cs" />
+ <Compile Include="com\foo\Simple.cs" />
+ <Compile Include="com\foo\Wide.cs" />
+ <Compile Include="PerfTest.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="schema.avsc" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below \
and uncomment it. + Other similar extension points exist, see \
Microsoft.Common.targets. + <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
\ No newline at end of file
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic