@@ -2645,15 +2645,18 @@ body
26452645
26462646/**
26472647Implements an output range that appends data to an array. This is
2648- recommended over $(D a ~= data) when appending many elements because it is more
2649- efficient.
2648+ recommended over $(D array ~= data) when appending many elements because it is more
2649+ efficient. `Appender` maintains its own array metadata locally, so it can avoid
2650+ global locking for each append where $(LREF capacity) is non-zero.
2651+ See_Also: $(LREF appender)
26502652 */
26512653struct Appender (A)
26522654if (isDynamicArray! A)
26532655{
26542656 import core.memory : GC ;
26552657
26562658 private alias T = ElementEncodingType! A;
2659+
26572660 private struct Data
26582661 {
26592662 size_t capacity ;
@@ -2664,12 +2667,12 @@ if (isDynamicArray!A)
26642667 private Data* _data;
26652668
26662669 /**
2667- * Construct an appender with a given array. Note that this does not copy the
2668- * data. If the array has a larger capacity as determined by arr.capacity,
2670+ * Constructs an `Appender` with a given array. Note that this does not copy the
2671+ * data. If the array has a larger capacity as determined by ` arr.capacity` ,
26692672 * it will be used by the appender. After initializing an appender on an array,
26702673 * appending to the original array will reallocate.
26712674 */
2672- this (T[] arr) @trusted pure nothrow
2675+ this (A arr) @trusted pure nothrow
26732676 {
26742677 // initialize to a given array.
26752678 _data = new Data;
@@ -2694,7 +2697,7 @@ if (isDynamicArray!A)
26942697
26952698 /**
26962699 * Reserve at least newCapacity elements for appending. Note that more elements
2697- * may be reserved than requested. If newCapacity <= capacity, then nothing is
2700+ * may be reserved than requested. If ` newCapacity <= capacity` , then nothing is
26982701 * done.
26992702 */
27002703 void reserve (size_t newCapacity) @safe pure nothrow
@@ -2723,7 +2726,7 @@ if (isDynamicArray!A)
27232726 /**
27242727 * Returns the managed array.
27252728 */
2726- @property inout (T )[] data() inout @trusted pure nothrow
2729+ @property inout (ElementEncodingType ! A )[] data() inout @trusted pure nothrow
27272730 {
27282731 /* @trusted operation:
27292732 * casting Unqual!T[] to inout(T)[]
@@ -2815,7 +2818,7 @@ if (isDynamicArray!A)
28152818 }
28162819
28172820 /**
2818- * Appends one item to the managed array.
2821+ * Appends ` item` to the managed array.
28192822 */
28202823 void put (U)(U item) if (canPutItem! U)
28212824 {
@@ -2888,7 +2891,7 @@ if (isDynamicArray!A)
28882891 alias UT = Unqual! T;
28892892
28902893 static if (is (typeof (_data.arr[] = items[])) &&
2891- ! hasElaborateAssign! (Unqual ! T) && isAssignable! (UT , ElementEncodingType! Range ))
2894+ ! hasElaborateAssign! UT && isAssignable! (UT , ElementEncodingType! Range ))
28922895 {
28932896 bigData[len .. newlen] = items[];
28942897 }
@@ -2917,25 +2920,14 @@ if (isDynamicArray!A)
29172920 }
29182921
29192922 /**
2920- * Appends one item to the managed array.
2921- */
2922- void opOpAssign (string op : " ~" , U)(U item) if (canPutItem! U)
2923- {
2924- put(item);
2925- }
2926-
2927- // Const fixing hack.
2928- void opOpAssign (string op : " ~" , Range )(Range items) if (canPutConstRange! Range )
2929- {
2930- put(items);
2931- }
2932-
2933- /**
2934- * Appends an entire range to the managed array.
2923+ * Appends `rhs` to the managed array.
2924+ * Params:
2925+ * rhs = Element or range.
29352926 */
2936- void opOpAssign (string op : " ~" , Range )(Range items) if (canPutRange! Range )
2927+ void opOpAssign (string op : " ~" , U)(U rhs)
2928+ if (__traits(compiles, put(rhs)))
29372929 {
2938- put(items );
2930+ put(rhs );
29392931 }
29402932
29412933 // only allow overwriting data on non-immutable and non-const data
@@ -2945,7 +2937,7 @@ if (isDynamicArray!A)
29452937 * Clears the managed array. This allows the elements of the array to be reused
29462938 * for appending.
29472939 *
2948- * Note that clear is disabled for immutable or const element types, due to the
2940+ * Note: clear is disabled for immutable or const element types, due to the
29492941 * possibility that $(D Appender) might overwrite immutable data.
29502942 */
29512943 void clear () @trusted pure nothrow
@@ -2960,6 +2952,7 @@ if (isDynamicArray!A)
29602952 * Shrinks the managed array to the given length.
29612953 *
29622954 * Throws: $(D Exception) if newlength is greater than the current array length.
2955+ * Note: shrinkTo is disabled for immutable or const element types.
29632956 */
29642957 void shrinkTo (size_t newlength) @trusted pure
29652958 {
@@ -3027,68 +3020,63 @@ private size_t appenderNewCapacity(size_t TSizeOf)(size_t curLen, size_t reqLen)
30273020}
30283021
30293022/**
3030- * An appender that can update an array in-place. It forwards all calls to an
3031- * underlying appender implementation. Any calls made to the appender also update
3032- * the pointer to the original array passed in.
3023+ * A version of $(LREF Appender) that can update an array in-place.
3024+ * It forwards all calls to an underlying appender implementation.
3025+ * Any calls made to the appender also update the pointer to the
3026+ * original array passed in.
3027+ *
3028+ * Tip: Use the `arrayPtr` overload of $(LREF appender) for construction with type-inference.
30333029 */
30343030struct RefAppender (A)
30353031if (isDynamicArray! A)
30363032{
30373033 private
30383034 {
3039- alias T = ElementEncodingType! A;
30403035 Appender! A impl;
3041- T[] * arr;
3036+ A * arr;
30423037 }
30433038
30443039 /**
3045- * Construct a ref appender with a given array reference. This does not copy the
3046- * data. If the array has a larger capacity as determined by arr.capacity, it
3047- * will be used by the appender. $(D RefAppender) assumes that arr is a non-null
3048- * value.
3040+ * Constructs a `RefAppender` with a given array reference. This does not copy the
3041+ * data. If the array has a larger capacity as determined by `arr.capacity`, it
3042+ * will be used by the appender.
3043+ *
3044+ * Note: Do not use built-in appending (i.e. `~=`) on the original array
3045+ * until you are done with the appender, because subsequent calls to the appender
3046+ * will reallocate the array data without those appends.
30493047 *
3050- * Note, do not use builtin appending (i.e. ~=) on the original array passed in
3051- * until you are done with the appender, because calls to the appender override
3052- * those appends.
3048+ * Params:
3049+ * arr = Pointer to an array. Must not be _null.
30533050 */
3054- this (T[] * arr)
3051+ this (A * arr)
30553052 {
30563053 impl = Appender! A(* arr);
30573054 this .arr = arr;
30583055 }
30593056
3060- void opDispatch (string fn, Args... )(Args args) if (is (typeof (mixin (" impl." ~ fn ~ " (args)" ))))
3057+ /* * Wraps remaining `Appender` methods such as $(LREF put).
3058+ * Params:
3059+ * fn = Method name to call.
3060+ * args = Arguments to pass to the method.
3061+ */
3062+ void opDispatch (string fn, Args... )(Args args)
3063+ if (__traits(compiles, (Appender! A a) => mixin (" a." ~ fn ~ " (args)" )))
30613064 {
30623065 // we do it this way because we can't cache a void return
30633066 scope (exit) * this .arr = impl.data;
30643067 mixin (" return impl." ~ fn ~ " (args);" );
30653068 }
30663069
3067- private alias AppenderType = Appender! A;
3068-
30693070 /**
3070- * Appends one item to the managed array.
3071- */
3072- void opOpAssign (string op : " ~" , U)(U item) if (AppenderType.canPutItem! U)
3073- {
3074- scope (exit) * this .arr = impl.data;
3075- impl.put(item);
3076- }
3077-
3078- // Const fixing hack.
3079- void opOpAssign (string op : " ~" , Range )(Range items) if (AppenderType.canPutConstRange! Range )
3080- {
3081- scope (exit) * this .arr = impl.data;
3082- impl.put(items);
3083- }
3084-
3085- /**
3086- * Appends an entire range to the managed array.
3071+ * Appends `rhs` to the managed array.
3072+ * Params:
3073+ * rhs = Element or range.
30873074 */
3088- void opOpAssign (string op : " ~" , Range )(Range items) if (AppenderType.canPutRange! Range )
3075+ void opOpAssign (string op : " ~" , U)(U rhs)
3076+ if (__traits(compiles, (Appender! A a){ a.put(rhs); }))
30893077 {
30903078 scope (exit) * this .arr = impl.data;
3091- impl.put(items );
3079+ impl.put(rhs );
30923080 }
30933081
30943082 /**
@@ -3104,15 +3092,15 @@ if (isDynamicArray!A)
31043092 /**
31053093 * Returns the managed array.
31063094 */
3107- @property inout (T )[] data() inout
3095+ @property inout (ElementEncodingType ! A )[] data() inout
31083096 {
31093097 return impl.data;
31103098 }
31113099}
31123100
31133101/+ +
3114- Convenience function that returns an $(D Appender!A) object initialized
3115- with $(D array).
3102+ Convenience function that returns an $(LREF Appender) instance,
3103+ optionally initialized with $(D array).
31163104 +/
31173105Appender! A appender (A)()
31183106if (isDynamicArray! A)
@@ -3486,13 +3474,13 @@ Appender!(E[]) appender(A : E[], E)(auto ref A array)
34863474}
34873475
34883476/+ +
3489- Convenience function that returns a $(D RefAppender!A) object initialized
3490- with $(D array). Don't use null for the $(D array) pointer, use the other
3477+ Convenience function that returns a $(LREF RefAppender) instance initialized
3478+ with `arrayPtr`. Don't use null for the array pointer, use the other
34913479 version of $(D appender) instead.
34923480 +/
3493- RefAppender! (E[]) appender (A : E[]* , E)(A array )
3481+ RefAppender! (E[]) appender (P : E[]* , E)(P arrayPtr )
34943482{
3495- return RefAppender! (E[])(array );
3483+ return RefAppender! (E[])(arrayPtr );
34963484}
34973485
34983486@system unittest
0 commit comments