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)
}