func()

in string.go [204:302]


func (d *Decoder) decString(flag int32) (string, error) {
	var (
		tag byte
		s   string
	)

	if flag != TAG_READ {
		tag = byte(flag)
	} else {
		tag, _ = d.ReadByte()
	}

	switch {
	case tag == BC_NULL:
		return STRING_NIL, nil

	case tag == BC_TRUE:
		return STRING_TRUE, nil

	case tag == BC_FALSE:
		return STRING_FALSE, nil

	case (0x80 <= tag && tag <= 0xbf) || (0xc0 <= tag && tag <= 0xcf) ||
		(0xd0 <= tag && tag <= 0xd7) || tag == BC_INT ||
		(tag >= 0xd8 && tag <= 0xef) || (tag >= 0xf0 && tag <= 0xff) ||
		(tag >= 0x38 && tag <= 0x3f) || (tag == BC_LONG_INT) || (tag == BC_LONG):
		i64, err := d.decInt64(int32(tag))
		if err != nil {
			return "", perrors.Wrapf(err, "tag:%+v", tag)
		}

		return strconv.Itoa(int(i64)), nil

	case tag == BC_DOUBLE_ZERO:
		return STRING_ZERO, nil

	case tag == BC_DOUBLE_ONE:
		return STRING_ONE, nil

	case tag == BC_DOUBLE_BYTE || tag == BC_DOUBLE_SHORT:
		f, err := d.decDouble(int32(tag))
		if err != nil {
			return "", perrors.Wrapf(err, "tag:%+v", tag)
		}

		return strconv.FormatFloat(f.(float64), 'E', -1, 64), nil
	}

	if (tag >= BC_STRING_DIRECT && tag <= STRING_DIRECT_MAX) ||
		(tag >= 0x30 && tag <= 0x33) ||
		(tag == BC_STRING_CHUNK || tag == BC_STRING) {

		if tag != BC_STRING_CHUNK {
			data, err := d.readStringChunkData(tag)
			if err != nil {
				return "", err
			}
			return *(*string)(unsafe.Pointer(&data)), nil
		}

		var chunkDataSlice [][]byte
		dataLength := 0

		for {
			data, err := d.readStringChunkData(tag)
			if err != nil {
				return "", err
			}

			chunkDataSlice = append(chunkDataSlice, data)
			dataLength += len(data)

			// last chunk
			if tag != BC_STRING_CHUNK {
				allData := make([]byte, dataLength)
				index := 0
				for _, b := range chunkDataSlice {
					copy(allData[index:], b)
					index += len(b)
				}
				return *(*string)(unsafe.Pointer(&allData)), nil
			}

			// read next string chunk tag
			tag, _ = d.ReadByte()
			switch {
			case (tag >= BC_STRING_DIRECT && tag <= STRING_DIRECT_MAX) ||
				(tag >= 0x30 && tag <= 0x33) ||
				(tag == BC_STRING_CHUNK || tag == BC_STRING):

			default:
				return s, perrors.New("expect string tag")
			}
		}

	}

	return s, perrors.Errorf("unknown string tag %#x\n", tag)
}