github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/libgo/runtime/go-int-array-to-string.c (about)

     1  /* go-int-array-to-string.c -- convert an array of ints to a string in Go.
     2  
     3     Copyright 2009 The Go Authors. All rights reserved.
     4     Use of this source code is governed by a BSD-style
     5     license that can be found in the LICENSE file.  */
     6  
     7  #include "go-assert.h"
     8  #include "runtime.h"
     9  #include "arch.h"
    10  #include "malloc.h"
    11  
    12  String
    13  __go_int_array_to_string (const void* p, intgo len)
    14  {
    15    const int32 *ints;
    16    intgo slen;
    17    intgo i;
    18    unsigned char *retdata;
    19    String ret;
    20    unsigned char *s;
    21  
    22    ints = (const int32 *) p;
    23  
    24    slen = 0;
    25    for (i = 0; i < len; ++i)
    26      {
    27        int32 v;
    28  
    29        v = ints[i];
    30  
    31        if (v < 0 || v > 0x10ffff)
    32  	v = 0xfffd;
    33        else if (0xd800 <= v && v <= 0xdfff)
    34  	v = 0xfffd;
    35  
    36        if (v <= 0x7f)
    37  	slen += 1;
    38        else if (v <= 0x7ff)
    39  	slen += 2;
    40        else if (v <= 0xffff)
    41  	slen += 3;
    42        else
    43  	slen += 4;
    44      }
    45  
    46    retdata = runtime_mallocgc ((uintptr) slen, 0, FlagNoScan);
    47    ret.str = retdata;
    48    ret.len = slen;
    49  
    50    s = retdata;
    51    for (i = 0; i < len; ++i)
    52      {
    53        int32 v;
    54  
    55        v = ints[i];
    56  
    57        /* If V is out of range for UTF-8, substitute the replacement
    58  	 character.  */
    59        if (v < 0 || v > 0x10ffff)
    60  	v = 0xfffd;
    61        else if (0xd800 <= v && v <= 0xdfff)
    62  	v = 0xfffd;
    63  
    64        if (v <= 0x7f)
    65  	*s++ = v;
    66        else if (v <= 0x7ff)
    67  	{
    68  	  *s++ = 0xc0 | ((v >> 6) & 0x1f);
    69  	  *s++ = 0x80 | (v & 0x3f);
    70  	}
    71        else if (v <= 0xffff)
    72  	{
    73  	  *s++ = 0xe0 | ((v >> 12) & 0xf);
    74  	  *s++ = 0x80 | ((v >> 6) & 0x3f);
    75  	  *s++ = 0x80 | (v & 0x3f);
    76  	}
    77        else
    78  	{
    79  	  *s++ = 0xf0 | ((v >> 18) & 0x7);
    80  	  *s++ = 0x80 | ((v >> 12) & 0x3f);
    81  	  *s++ = 0x80 | ((v >> 6) & 0x3f);
    82  	  *s++ = 0x80 | (v & 0x3f);
    83  	}
    84      }
    85  
    86    __go_assert (s - retdata == slen);
    87  
    88    return ret;
    89  }