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

     1  /* go-rune.c -- rune functions for Go.
     2  
     3     Copyright 2009, 2010 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 <stddef.h>
     8  
     9  #include "runtime.h"
    10  #include "go-string.h"
    11  
    12  /* Get a character from the UTF-8 string STR, of length LEN.  Store
    13     the Unicode character, if any, in *RUNE.  Return the number of
    14     characters used from STR.  */
    15  
    16  int
    17  __go_get_rune (const unsigned char *str, size_t len, int32 *rune)
    18  {
    19    int c, c1, c2, c3, l;
    20  
    21    /* Default to the "replacement character".  */
    22    *rune = 0xfffd;
    23  
    24    if (len <= 0)
    25      return 1;
    26  
    27    c = *str;
    28    if (c <= 0x7f)
    29      {
    30        *rune = c;
    31        return 1;
    32      }
    33  
    34    if (len <= 1)
    35      return 1;
    36  
    37    c1 = str[1];
    38    if ((c & 0xe0) == 0xc0
    39        && (c1 & 0xc0) == 0x80)
    40      {
    41        l = (((c & 0x1f) << 6) + (c1 & 0x3f));
    42        if (l <= 0x7f)
    43  	return 1;
    44        *rune = l;
    45        return 2;
    46      }
    47  
    48    if (len <= 2)
    49      return 1;
    50  
    51    c2 = str[2];
    52    if ((c & 0xf0) == 0xe0
    53        && (c1 & 0xc0) == 0x80
    54        && (c2 & 0xc0) == 0x80)
    55      {
    56        l = (((c & 0xf) << 12)
    57  	   + ((c1 & 0x3f) << 6)
    58  	   + (c2 & 0x3f));
    59  
    60        if (l <= 0x7ff)
    61  	return 1;
    62  
    63        if (l >= 0xd800 && l < 0xe000)
    64  	{
    65  	  /* Invalid surrogate half; return replace character.  */
    66  	  return 1;
    67  	}
    68  
    69        *rune = l;
    70  
    71        return 3;
    72      }
    73  
    74    if (len <= 3)
    75      return 1;
    76  
    77    c3 = str[3];
    78    if ((c & 0xf8) == 0xf0
    79        && (c1 & 0xc0) == 0x80
    80        && (c2 & 0xc0) == 0x80
    81        && (c3 & 0xc0) == 0x80)
    82      {
    83        l = (((c & 0x7) << 18)
    84  	   + ((c1 & 0x3f) << 12)
    85  	   + ((c2 & 0x3f) << 6)
    86  	   + (c3 & 0x3f));
    87  
    88        if (l <= 0xffff || l > 0x10ffff)
    89  	return 1;
    90  
    91        *rune = l;
    92        return 4;
    93      }
    94  
    95    /* Invalid encoding.  Return 1 so that we advance.  */
    96    return 1;
    97  }