mirror of
https://github.com/golang/go
synced 2024-11-24 17:00:01 -07:00
runtime: append([]byte, string...)
Fixes #2274 R=rsc, gri, dsymonds, bradfitz, lvd CC=golang-dev https://golang.org/cl/5149045
This commit is contained in:
parent
a0d335c31d
commit
77fac21e82
@ -1,5 +1,5 @@
|
|||||||
<!-- title The Go Programming Language Specification -->
|
<!-- title The Go Programming Language Specification -->
|
||||||
<!-- subtitle Version of August 31, 2011 -->
|
<!-- subtitle Version of September 29, 2011 -->
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
TODO
|
TODO
|
||||||
@ -4658,6 +4658,10 @@ The values <code>x</code> are passed to a parameter of type <code>...T</code>
|
|||||||
where <code>T</code> is the <a href="#Slice_types">element type</a> of
|
where <code>T</code> is the <a href="#Slice_types">element type</a> of
|
||||||
<code>S</code> and the respective
|
<code>S</code> and the respective
|
||||||
<a href="#Passing_arguments_to_..._parameters">parameter passing rules</a> apply.
|
<a href="#Passing_arguments_to_..._parameters">parameter passing rules</a> apply.
|
||||||
|
As a special case, <code>append</code> also accepts a first argument
|
||||||
|
assignable to type <code>[]byte</code> with a second argument of
|
||||||
|
string type followed by <code>...</code>. This form appends the
|
||||||
|
bytes of the string.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre class="grammar">
|
<pre class="grammar">
|
||||||
@ -4668,7 +4672,7 @@ append(s S, x ...T) S // T is the element type of S
|
|||||||
If the capacity of <code>s</code> is not large enough to fit the additional
|
If the capacity of <code>s</code> is not large enough to fit the additional
|
||||||
values, <code>append</code> allocates a new, sufficiently large slice that fits
|
values, <code>append</code> allocates a new, sufficiently large slice that fits
|
||||||
both the existing slice elements and the additional values. Thus, the returned
|
both the existing slice elements and the additional values. Thus, the returned
|
||||||
slice may refer to a different underlying array.
|
slice may refer to a different underlying array.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@ -4679,6 +4683,9 @@ s3 := append(s2, s0...) // append a slice s3 == []int{0, 0, 2, 3
|
|||||||
|
|
||||||
var t []interface{}
|
var t []interface{}
|
||||||
t = append(t, 42, 3.1415, "foo") t == []interface{}{42, 3.1415, "foo"}
|
t = append(t, 42, 3.1415, "foo") t == []interface{}{42, 3.1415, "foo"}
|
||||||
|
|
||||||
|
var b []byte
|
||||||
|
b = append(b, "bar"...) // append string contents b == []byte{'b', 'a', 'r' }
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -25,6 +25,7 @@ char *runtimeimport =
|
|||||||
"func @\"\".concatstring ()\n"
|
"func @\"\".concatstring ()\n"
|
||||||
"func @\"\".append ()\n"
|
"func @\"\".append ()\n"
|
||||||
"func @\"\".appendslice (typ *uint8, x any, y []any) any\n"
|
"func @\"\".appendslice (typ *uint8, x any, y []any) any\n"
|
||||||
|
"func @\"\".appendstr (typ *uint8, x []uint8, y string) []uint8\n"
|
||||||
"func @\"\".cmpstring (? string, ? string) int\n"
|
"func @\"\".cmpstring (? string, ? string) int\n"
|
||||||
"func @\"\".slicestring (? string, ? int, ? int) string\n"
|
"func @\"\".slicestring (? string, ? int, ? int) string\n"
|
||||||
"func @\"\".slicestring1 (? string, ? int) string\n"
|
"func @\"\".slicestring1 (? string, ? int) string\n"
|
||||||
|
@ -40,6 +40,7 @@ func concatstring()
|
|||||||
// filled in by compiler: Type*, int n, Slice, ...
|
// filled in by compiler: Type*, int n, Slice, ...
|
||||||
func append()
|
func append()
|
||||||
func appendslice(typ *byte, x any, y []any) any
|
func appendslice(typ *byte, x any, y []any) any
|
||||||
|
func appendstr(typ *byte, x []byte, y string) []byte
|
||||||
|
|
||||||
func cmpstring(string, string) int
|
func cmpstring(string, string) int
|
||||||
func slicestring(string, int, int) string
|
func slicestring(string, int, int) string
|
||||||
|
@ -1008,6 +1008,10 @@ reswitch:
|
|||||||
yyerror("too many arguments to append");
|
yyerror("too many arguments to append");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if(istype(t->type, TUINT8) && istype(args->next->n->type, TSTRING)) {
|
||||||
|
defaultlit(&args->next->n, types[TSTRING]);
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
args->next->n = assignconv(args->next->n, t->orig, "append");
|
args->next->n = assignconv(args->next->n, t->orig, "append");
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
@ -1039,7 +1043,7 @@ reswitch:
|
|||||||
goto error;
|
goto error;
|
||||||
defaultlit(&n->left, T);
|
defaultlit(&n->left, T);
|
||||||
defaultlit(&n->right, T);
|
defaultlit(&n->right, T);
|
||||||
|
|
||||||
// copy([]byte, string)
|
// copy([]byte, string)
|
||||||
if(isslice(n->left->type) && n->right->type->etype == TSTRING) {
|
if(isslice(n->left->type) && n->right->type->etype == TSTRING) {
|
||||||
if(n->left->type->type == types[TUINT8])
|
if(n->left->type->type == types[TUINT8])
|
||||||
@ -1047,7 +1051,7 @@ reswitch:
|
|||||||
yyerror("arguments to copy have different element types: %lT and string", n->left->type);
|
yyerror("arguments to copy have different element types: %lT and string", n->left->type);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isslice(n->left->type) || !isslice(n->right->type)) {
|
if(!isslice(n->left->type) || !isslice(n->right->type)) {
|
||||||
if(!isslice(n->left->type) && !isslice(n->right->type))
|
if(!isslice(n->left->type) && !isslice(n->right->type))
|
||||||
yyerror("arguments to copy must be slices; have %lT, %lT", n->left->type, n->right->type);
|
yyerror("arguments to copy must be slices; have %lT, %lT", n->left->type, n->right->type);
|
||||||
|
@ -121,7 +121,7 @@ static int
|
|||||||
paramoutheap(Node *fn)
|
paramoutheap(Node *fn)
|
||||||
{
|
{
|
||||||
NodeList *l;
|
NodeList *l;
|
||||||
|
|
||||||
for(l=fn->dcl; l; l=l->next) {
|
for(l=fn->dcl; l; l=l->next) {
|
||||||
switch(l->n->class) {
|
switch(l->n->class) {
|
||||||
case PPARAMOUT|PHEAP:
|
case PPARAMOUT|PHEAP:
|
||||||
@ -409,7 +409,7 @@ walkexpr(Node **np, NodeList **init)
|
|||||||
case OLEN:
|
case OLEN:
|
||||||
case OCAP:
|
case OCAP:
|
||||||
walkexpr(&n->left, init);
|
walkexpr(&n->left, init);
|
||||||
|
|
||||||
// replace len(*[10]int) with 10.
|
// replace len(*[10]int) with 10.
|
||||||
// delayed until now to preserve side effects.
|
// delayed until now to preserve side effects.
|
||||||
t = n->left->type;
|
t = n->left->type;
|
||||||
@ -421,7 +421,7 @@ walkexpr(Node **np, NodeList **init)
|
|||||||
n->typecheck = 1;
|
n->typecheck = 1;
|
||||||
}
|
}
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OLSH:
|
case OLSH:
|
||||||
case ORSH:
|
case ORSH:
|
||||||
case OAND:
|
case OAND:
|
||||||
@ -440,7 +440,7 @@ walkexpr(Node **np, NodeList **init)
|
|||||||
walkexpr(&n->left, init);
|
walkexpr(&n->left, init);
|
||||||
walkexpr(&n->right, init);
|
walkexpr(&n->right, init);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OANDAND:
|
case OANDAND:
|
||||||
case OOROR:
|
case OOROR:
|
||||||
walkexpr(&n->left, init);
|
walkexpr(&n->left, init);
|
||||||
@ -553,7 +553,7 @@ walkexpr(Node **np, NodeList **init)
|
|||||||
walkexprlistsafe(n->list, init);
|
walkexprlistsafe(n->list, init);
|
||||||
walkexpr(&r, init);
|
walkexpr(&r, init);
|
||||||
l = n->list->n;
|
l = n->list->n;
|
||||||
|
|
||||||
// all the really hard stuff - explicit function calls and so on -
|
// all the really hard stuff - explicit function calls and so on -
|
||||||
// is gone, but map assignments remain.
|
// is gone, but map assignments remain.
|
||||||
// if there are map assignments here, assign via
|
// if there are map assignments here, assign via
|
||||||
@ -648,7 +648,7 @@ walkexpr(Node **np, NodeList **init)
|
|||||||
if(n->op == ODOTTYPE2)
|
if(n->op == ODOTTYPE2)
|
||||||
*p++ = '2';
|
*p++ = '2';
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
|
|
||||||
fn = syslook(buf, 1);
|
fn = syslook(buf, 1);
|
||||||
ll = list1(typename(n->type));
|
ll = list1(typename(n->type));
|
||||||
ll = list(ll, n->left);
|
ll = list(ll, n->left);
|
||||||
@ -679,7 +679,7 @@ walkexpr(Node **np, NodeList **init)
|
|||||||
else
|
else
|
||||||
*p++ = 'I';
|
*p++ = 'I';
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
|
|
||||||
fn = syslook(buf, 1);
|
fn = syslook(buf, 1);
|
||||||
ll = nil;
|
ll = nil;
|
||||||
if(!isinter(n->left->type))
|
if(!isinter(n->left->type))
|
||||||
@ -894,7 +894,7 @@ walkexpr(Node **np, NodeList **init)
|
|||||||
}
|
}
|
||||||
if(v1 >= 0 && v2 >= 0 && v1 > v2)
|
if(v1 >= 0 && v2 >= 0 && v1 > v2)
|
||||||
yyerror("inverted slice range");
|
yyerror("inverted slice range");
|
||||||
|
|
||||||
if(n->op == OSLICEARR)
|
if(n->op == OSLICEARR)
|
||||||
goto slicearray;
|
goto slicearray;
|
||||||
|
|
||||||
@ -925,7 +925,7 @@ walkexpr(Node **np, NodeList **init)
|
|||||||
l,
|
l,
|
||||||
nodintconst(t->type->width));
|
nodintconst(t->type->width));
|
||||||
}
|
}
|
||||||
n->etype = et; // preserve no-typecheck flag from OSLICE to the slice* call.
|
n->etype = et; // preserve no-typecheck flag from OSLICE to the slice* call.
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
slicearray:
|
slicearray:
|
||||||
@ -1054,10 +1054,14 @@ walkexpr(Node **np, NodeList **init)
|
|||||||
l);
|
l);
|
||||||
}
|
}
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OAPPEND:
|
case OAPPEND:
|
||||||
if(n->isddd)
|
if(n->isddd) {
|
||||||
n = appendslice(n, init);
|
if(istype(n->type->type, TUINT8) && istype(n->list->next->n->type, TSTRING))
|
||||||
|
n = mkcall("appendstr", n->type, init, typename(n->type), n->list->n, n->list->next->n);
|
||||||
|
else
|
||||||
|
n = appendslice(n, init);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
n = append(n, init);
|
n = append(n, init);
|
||||||
goto ret;
|
goto ret;
|
||||||
@ -1319,7 +1323,7 @@ mkdotargslice(NodeList *lr0, NodeList *nn, Type *l, int fp, NodeList **init, int
|
|||||||
{
|
{
|
||||||
Node *a, *n;
|
Node *a, *n;
|
||||||
Type *tslice;
|
Type *tslice;
|
||||||
|
|
||||||
tslice = typ(TARRAY);
|
tslice = typ(TARRAY);
|
||||||
tslice->type = l->type->type;
|
tslice->type = l->type->type;
|
||||||
tslice->bound = -1;
|
tslice->bound = -1;
|
||||||
@ -1413,7 +1417,7 @@ ascompatte(int op, Node *call, int isddd, Type **nl, NodeList *lr, int fp, NodeL
|
|||||||
if(lr)
|
if(lr)
|
||||||
r = lr->n;
|
r = lr->n;
|
||||||
nn = nil;
|
nn = nil;
|
||||||
|
|
||||||
// f(g()) where g has multiple return values
|
// f(g()) where g has multiple return values
|
||||||
if(r != N && lr->next == nil && r->type->etype == TSTRUCT && r->type->funarg) {
|
if(r != N && lr->next == nil && r->type->etype == TSTRUCT && r->type->funarg) {
|
||||||
// optimization - can do block copy
|
// optimization - can do block copy
|
||||||
@ -1423,7 +1427,7 @@ ascompatte(int op, Node *call, int isddd, Type **nl, NodeList *lr, int fp, NodeL
|
|||||||
nn = list1(convas(nod(OAS, a, r), init));
|
nn = list1(convas(nod(OAS, a, r), init));
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// conversions involved.
|
// conversions involved.
|
||||||
// copy into temporaries.
|
// copy into temporaries.
|
||||||
alist = nil;
|
alist = nil;
|
||||||
@ -1714,10 +1718,10 @@ convas(Node *n, NodeList **init)
|
|||||||
n->left->left, n->left->right, n->right);
|
n->left->left, n->left->right, n->right);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(eqtype(lt, rt))
|
if(eqtype(lt, rt))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
n->right = assignconv(n->right, lt, "assignment");
|
n->right = assignconv(n->right, lt, "assignment");
|
||||||
walkexpr(&n->right, init);
|
walkexpr(&n->right, init);
|
||||||
|
|
||||||
@ -1952,7 +1956,7 @@ heapmoves(void)
|
|||||||
{
|
{
|
||||||
NodeList *nn;
|
NodeList *nn;
|
||||||
int32 lno;
|
int32 lno;
|
||||||
|
|
||||||
lno = lineno;
|
lno = lineno;
|
||||||
lineno = curfn->lineno;
|
lineno = curfn->lineno;
|
||||||
nn = paramstoheap(getthis(curfn->type), 0);
|
nn = paramstoheap(getthis(curfn->type), 0);
|
||||||
@ -2060,7 +2064,7 @@ addstr(Node *n, NodeList **init)
|
|||||||
Node *r, *cat, *typstr;
|
Node *r, *cat, *typstr;
|
||||||
NodeList *in, *args;
|
NodeList *in, *args;
|
||||||
int i, count;
|
int i, count;
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
for(r=n; r->op == OADDSTR; r=r->left)
|
for(r=n; r->op == OADDSTR; r=r->left)
|
||||||
count++; // r->right
|
count++; // r->right
|
||||||
@ -2089,7 +2093,7 @@ addstr(Node *n, NodeList **init)
|
|||||||
typecheck(&r, Erv);
|
typecheck(&r, Erv);
|
||||||
walkexpr(&r, init);
|
walkexpr(&r, init);
|
||||||
r->type = n->type;
|
r->type = n->type;
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2097,7 +2101,7 @@ static Node*
|
|||||||
appendslice(Node *n, NodeList **init)
|
appendslice(Node *n, NodeList **init)
|
||||||
{
|
{
|
||||||
Node *f;
|
Node *f;
|
||||||
|
|
||||||
f = syslook("appendslice", 1);
|
f = syslook("appendslice", 1);
|
||||||
argtype(f, n->type);
|
argtype(f, n->type);
|
||||||
argtype(f, n->type->type);
|
argtype(f, n->type->type);
|
||||||
@ -2111,7 +2115,7 @@ appendslice(Node *n, NodeList **init)
|
|||||||
// s := src
|
// s := src
|
||||||
// const argc = len(args) - 1
|
// const argc = len(args) - 1
|
||||||
// if cap(s) - len(s) < argc {
|
// if cap(s) - len(s) < argc {
|
||||||
// s = growslice(s, argc)
|
// s = growslice(s, argc)
|
||||||
// }
|
// }
|
||||||
// n := len(s)
|
// n := len(s)
|
||||||
// s = s[:n+argc]
|
// s = s[:n+argc]
|
||||||
@ -2140,13 +2144,13 @@ append(Node *n, NodeList **init)
|
|||||||
ns = temp(nsrc->type);
|
ns = temp(nsrc->type);
|
||||||
l = list(l, nod(OAS, ns, nsrc)); // s = src
|
l = list(l, nod(OAS, ns, nsrc)); // s = src
|
||||||
|
|
||||||
na = nodintconst(argc); // const argc
|
na = nodintconst(argc); // const argc
|
||||||
nx = nod(OIF, N, N); // if cap(s) - len(s) < argc
|
nx = nod(OIF, N, N); // if cap(s) - len(s) < argc
|
||||||
nx->ntest = nod(OLT, nod(OSUB, nod(OCAP, ns, N), nod(OLEN, ns, N)), na);
|
nx->ntest = nod(OLT, nod(OSUB, nod(OCAP, ns, N), nod(OLEN, ns, N)), na);
|
||||||
|
|
||||||
fn = syslook("growslice", 1); // growslice(<type>, old []T, n int64) (ret []T)
|
fn = syslook("growslice", 1); // growslice(<type>, old []T, n int64) (ret []T)
|
||||||
argtype(fn, ns->type->type); // 1 old []any
|
argtype(fn, ns->type->type); // 1 old []any
|
||||||
argtype(fn, ns->type->type); // 2 ret []any
|
argtype(fn, ns->type->type); // 2 ret []any
|
||||||
|
|
||||||
nx->nbody = list1(nod(OAS, ns, mkcall1(fn, ns->type, &nx->ninit,
|
nx->nbody = list1(nod(OAS, ns, mkcall1(fn, ns->type, &nx->ninit,
|
||||||
typename(ns->type),
|
typename(ns->type),
|
||||||
@ -2155,16 +2159,16 @@ append(Node *n, NodeList **init)
|
|||||||
l = list(l, nx);
|
l = list(l, nx);
|
||||||
|
|
||||||
nn = temp(types[TINT]);
|
nn = temp(types[TINT]);
|
||||||
l = list(l, nod(OAS, nn, nod(OLEN, ns, N))); // n = len(s)
|
l = list(l, nod(OAS, nn, nod(OLEN, ns, N))); // n = len(s)
|
||||||
|
|
||||||
nx = nod(OSLICE, ns, nod(OKEY, N, nod(OADD, nn, na))); // ...s[:n+argc]
|
nx = nod(OSLICE, ns, nod(OKEY, N, nod(OADD, nn, na))); // ...s[:n+argc]
|
||||||
nx->etype = 1; // disable bounds check
|
nx->etype = 1; // disable bounds check
|
||||||
l = list(l, nod(OAS, ns, nx)); // s = s[:n+argc]
|
l = list(l, nod(OAS, ns, nx)); // s = s[:n+argc]
|
||||||
|
|
||||||
for (a = n->list->next; a != nil; a = a->next) {
|
for (a = n->list->next; a != nil; a = a->next) {
|
||||||
nx = nod(OINDEX, ns, nn); // s[n] ...
|
nx = nod(OINDEX, ns, nn); // s[n] ...
|
||||||
nx->etype = 1; // disable bounds check
|
nx->etype = 1; // disable bounds check
|
||||||
l = list(l, nod(OAS, nx, a->n)); // s[n] = arg
|
l = list(l, nod(OAS, nx, a->n)); // s[n] = arg
|
||||||
if (a->next != nil)
|
if (a->next != nil)
|
||||||
l = list(l, nod(OAS, nn, nod(OADD, nn, nodintconst(1)))); // n = n + 1
|
l = list(l, nod(OAS, nn, nod(OADD, nn, nodintconst(1)))); // n = n + 1
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ static int32 debug = 0;
|
|||||||
|
|
||||||
static void makeslice1(SliceType*, int32, int32, Slice*);
|
static void makeslice1(SliceType*, int32, int32, Slice*);
|
||||||
static void growslice1(SliceType*, Slice, int32, Slice *);
|
static void growslice1(SliceType*, Slice, int32, Slice *);
|
||||||
static void appendslice1(SliceType*, Slice, Slice, Slice*);
|
|
||||||
void runtime·slicecopy(Slice to, Slice fm, uintptr width, int32 ret);
|
void runtime·slicecopy(Slice to, Slice fm, uintptr width, int32 ret);
|
||||||
|
|
||||||
// see also unsafe·NewArray
|
// see also unsafe·NewArray
|
||||||
@ -29,13 +28,13 @@ runtime·makeslice(SliceType *t, int64 len, int64 cap, Slice ret)
|
|||||||
if(debug) {
|
if(debug) {
|
||||||
runtime·printf("makeslice(%S, %D, %D); ret=",
|
runtime·printf("makeslice(%S, %D, %D); ret=",
|
||||||
*t->string, len, cap);
|
*t->string, len, cap);
|
||||||
runtime·printslice(ret);
|
runtime·printslice(ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
makeslice1(SliceType *t, int32 len, int32 cap, Slice *ret)
|
makeslice1(SliceType *t, int32 len, int32 cap, Slice *ret)
|
||||||
{
|
{
|
||||||
uintptr size;
|
uintptr size;
|
||||||
|
|
||||||
size = cap*t->elem->size;
|
size = cap*t->elem->size;
|
||||||
@ -52,12 +51,6 @@ makeslice1(SliceType *t, int32 len, int32 cap, Slice *ret)
|
|||||||
// appendslice(type *Type, x, y, []T) []T
|
// appendslice(type *Type, x, y, []T) []T
|
||||||
void
|
void
|
||||||
runtime·appendslice(SliceType *t, Slice x, Slice y, Slice ret)
|
runtime·appendslice(SliceType *t, Slice x, Slice y, Slice ret)
|
||||||
{
|
|
||||||
appendslice1(t, x, y, &ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
appendslice1(SliceType *t, Slice x, Slice y, Slice *ret)
|
|
||||||
{
|
{
|
||||||
int32 m;
|
int32 m;
|
||||||
uintptr w;
|
uintptr w;
|
||||||
@ -68,15 +61,39 @@ appendslice1(SliceType *t, Slice x, Slice y, Slice *ret)
|
|||||||
runtime·throw("append: slice overflow");
|
runtime·throw("append: slice overflow");
|
||||||
|
|
||||||
if(m > x.cap)
|
if(m > x.cap)
|
||||||
growslice1(t, x, m, ret);
|
growslice1(t, x, m, &ret);
|
||||||
else
|
else
|
||||||
*ret = x;
|
ret = x;
|
||||||
|
|
||||||
w = t->elem->size;
|
w = t->elem->size;
|
||||||
runtime·memmove(ret->array + ret->len*w, y.array, y.len*w);
|
runtime·memmove(ret.array + ret.len*w, y.array, y.len*w);
|
||||||
ret->len += y.len;
|
ret.len += y.len;
|
||||||
|
FLUSH(&ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// appendstr([]byte, string) []byte
|
||||||
|
void
|
||||||
|
runtime·appendstr(SliceType *t, Slice x, String y, Slice ret)
|
||||||
|
{
|
||||||
|
int32 m;
|
||||||
|
|
||||||
|
m = x.len+y.len;
|
||||||
|
|
||||||
|
if(m < x.len)
|
||||||
|
runtime·throw("append: slice overflow");
|
||||||
|
|
||||||
|
if(m > x.cap)
|
||||||
|
growslice1(t, x, m, &ret);
|
||||||
|
else
|
||||||
|
ret = x;
|
||||||
|
|
||||||
|
runtime·memmove(ret.array + ret.len, y.str, y.len);
|
||||||
|
ret.len += y.len;
|
||||||
|
FLUSH(&ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// growslice(type *Type, x, []T, n int64) []T
|
// growslice(type *Type, x, []T, n int64) []T
|
||||||
void
|
void
|
||||||
runtime·growslice(SliceType *t, Slice old, int64 n, Slice ret)
|
runtime·growslice(SliceType *t, Slice old, int64 n, Slice ret)
|
||||||
@ -97,9 +114,9 @@ runtime·growslice(SliceType *t, Slice old, int64 n, Slice ret)
|
|||||||
|
|
||||||
if(debug) {
|
if(debug) {
|
||||||
runtime·printf("growslice(%S,", *t->string);
|
runtime·printf("growslice(%S,", *t->string);
|
||||||
runtime·printslice(old);
|
runtime·printslice(old);
|
||||||
runtime·printf(", new cap=%D) =", cap);
|
runtime·printf(", new cap=%D) =", cap);
|
||||||
runtime·printslice(ret);
|
runtime·printslice(ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,11 +325,11 @@ runtime·slicestringcopy(Slice to, String fm, int32 ret)
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = fm.len;
|
ret = fm.len;
|
||||||
if(to.len < ret)
|
if(to.len < ret)
|
||||||
ret = to.len;
|
ret = to.len;
|
||||||
|
|
||||||
runtime·memmove(to.array, fm.str, ret);
|
runtime·memmove(to.array, fm.str, ret);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -63,6 +63,11 @@ var tests = []struct {
|
|||||||
{"byte i", append([]byte{0, 1, 2}, []byte{3}...), []byte{0, 1, 2, 3}},
|
{"byte i", append([]byte{0, 1, 2}, []byte{3}...), []byte{0, 1, 2, 3}},
|
||||||
{"byte j", append([]byte{0, 1, 2}, []byte{3, 4, 5}...), []byte{0, 1, 2, 3, 4, 5}},
|
{"byte j", append([]byte{0, 1, 2}, []byte{3, 4, 5}...), []byte{0, 1, 2, 3, 4, 5}},
|
||||||
|
|
||||||
|
{"bytestr a", append([]byte{}, "0"...), []byte("0")},
|
||||||
|
{"bytestr b", append([]byte{}, "0123"...), []byte("0123")},
|
||||||
|
|
||||||
|
{"bytestr c", append([]byte("012"), "3"...), []byte("0123")},
|
||||||
|
{"bytestr d", append([]byte("012"), "345"...), []byte("012345")},
|
||||||
|
|
||||||
{"int16 a", append([]int16{}), []int16{}},
|
{"int16 a", append([]int16{}), []int16{}},
|
||||||
{"int16 b", append([]int16{}, 0), []int16{0}},
|
{"int16 b", append([]int16{}, 0), []int16{0}},
|
||||||
|
Loading…
Reference in New Issue
Block a user