Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
87783933
Commit
87783933
authored
Jul 07, 2009
by
Russ Cox
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
gob: use new reflect
R=r DELTA=242 (68 added, 69 deleted, 105 changed) OCL=31239 CL=31289
parent
e37f81b4
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
169 additions
and
170 deletions
+169
-170
src/pkg/gob/decode.go
src/pkg/gob/decode.go
+52
-61
src/pkg/gob/encode.go
src/pkg/gob/encode.go
+54
-79
src/pkg/gob/type.go
src/pkg/gob/type.go
+63
-30
No files found.
src/pkg/gob/decode.go
View file @
87783933
...
@@ -278,7 +278,7 @@ type decEngine struct {
...
@@ -278,7 +278,7 @@ type decEngine struct {
instr
[]
decInstr
instr
[]
decInstr
}
}
func
decodeStruct
(
engine
*
decEngine
,
rtyp
reflect
.
StructType
,
r
io
.
Reader
,
p
uintptr
,
indir
int
)
os
.
Error
{
func
decodeStruct
(
engine
*
decEngine
,
rtyp
*
reflect
.
StructType
,
r
io
.
Reader
,
p
uintptr
,
indir
int
)
os
.
Error
{
if
indir
>
0
{
if
indir
>
0
{
up
:=
unsafe
.
Pointer
(
p
);
up
:=
unsafe
.
Pointer
(
p
);
if
*
(
*
unsafe
.
Pointer
)(
up
)
==
nil
{
if
*
(
*
unsafe
.
Pointer
)(
up
)
==
nil
{
...
@@ -317,7 +317,7 @@ func decodeStruct(engine *decEngine, rtyp reflect.StructType, r io.Reader, p uin
...
@@ -317,7 +317,7 @@ func decodeStruct(engine *decEngine, rtyp reflect.StructType, r io.Reader, p uin
return
state
.
err
return
state
.
err
}
}
func
decodeArrayHelper
(
state
*
DecState
,
p
uintptr
,
elemOp
decOp
,
elemWid
,
length
,
elemIndir
int
)
os
.
Error
{
func
decodeArrayHelper
(
state
*
DecState
,
p
uintptr
,
elemOp
decOp
,
elemWid
uintptr
,
length
,
elemIndir
int
)
os
.
Error
{
instr
:=
&
decInstr
{
elemOp
,
0
,
elemIndir
,
0
};
instr
:=
&
decInstr
{
elemOp
,
0
,
elemIndir
,
0
};
for
i
:=
0
;
i
<
length
&&
state
.
err
==
nil
;
i
++
{
for
i
:=
0
;
i
<
length
&&
state
.
err
==
nil
;
i
++
{
up
:=
unsafe
.
Pointer
(
p
);
up
:=
unsafe
.
Pointer
(
p
);
...
@@ -330,7 +330,7 @@ func decodeArrayHelper(state *DecState, p uintptr, elemOp decOp, elemWid, length
...
@@ -330,7 +330,7 @@ func decodeArrayHelper(state *DecState, p uintptr, elemOp decOp, elemWid, length
return
state
.
err
return
state
.
err
}
}
func
decodeArray
(
atyp
reflect
.
ArrayType
,
state
*
DecState
,
p
uintptr
,
elemOp
decOp
,
elemWid
,
length
,
indir
,
elemIndir
int
)
os
.
Error
{
func
decodeArray
(
atyp
*
reflect
.
ArrayType
,
state
*
DecState
,
p
uintptr
,
elemOp
decOp
,
elemWid
uintptr
,
length
,
indir
,
elemIndir
int
)
os
.
Error
{
if
indir
>
0
{
if
indir
>
0
{
up
:=
unsafe
.
Pointer
(
p
);
up
:=
unsafe
.
Pointer
(
p
);
if
*
(
*
unsafe
.
Pointer
)(
up
)
==
nil
{
if
*
(
*
unsafe
.
Pointer
)(
up
)
==
nil
{
...
@@ -341,14 +341,14 @@ func decodeArray(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decO
...
@@ -341,14 +341,14 @@ func decodeArray(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decO
}
}
p
=
*
(
*
uintptr
)(
up
);
p
=
*
(
*
uintptr
)(
up
);
}
}
if
DecodeUint
(
state
)
!=
uint64
(
length
)
{
if
n
:=
DecodeUint
(
state
);
n
!=
uint64
(
length
)
{
return
os
.
ErrorString
(
"length mismatch in decodeArray"
);
return
os
.
ErrorString
(
"length mismatch in decodeArray"
);
}
}
return
decodeArrayHelper
(
state
,
p
,
elemOp
,
elemWid
,
length
,
elemIndir
);
return
decodeArrayHelper
(
state
,
p
,
elemOp
,
elemWid
,
length
,
elemIndir
);
}
}
func
decodeSlice
(
atyp
reflect
.
ArrayType
,
state
*
DecState
,
p
uintptr
,
elemOp
decOp
,
elemWid
,
indir
,
elemIndir
int
)
os
.
Error
{
func
decodeSlice
(
atyp
*
reflect
.
SliceType
,
state
*
DecState
,
p
uintptr
,
elemOp
decOp
,
elemWid
uintptr
,
indir
,
elemIndir
int
)
os
.
Error
{
length
:=
int
(
DecodeUint
(
state
));
length
:=
uintptr
(
DecodeUint
(
state
));
if
indir
>
0
{
if
indir
>
0
{
up
:=
unsafe
.
Pointer
(
p
);
up
:=
unsafe
.
Pointer
(
p
);
if
*
(
*
unsafe
.
Pointer
)(
up
)
==
nil
{
if
*
(
*
unsafe
.
Pointer
)(
up
)
==
nil
{
...
@@ -364,59 +364,58 @@ func decodeSlice(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decO
...
@@ -364,59 +364,58 @@ func decodeSlice(atyp reflect.ArrayType, state *DecState, p uintptr, elemOp decO
hdrp
.
Data
=
uintptr
(
unsafe
.
Pointer
(
&
data
[
0
]));
hdrp
.
Data
=
uintptr
(
unsafe
.
Pointer
(
&
data
[
0
]));
hdrp
.
Len
=
uint32
(
length
);
hdrp
.
Len
=
uint32
(
length
);
hdrp
.
Cap
=
uint32
(
length
);
hdrp
.
Cap
=
uint32
(
length
);
return
decodeArrayHelper
(
state
,
hdrp
.
Data
,
elemOp
,
elemWid
,
length
,
elemIndir
);
return
decodeArrayHelper
(
state
,
hdrp
.
Data
,
elemOp
,
elemWid
,
int
(
length
)
,
elemIndir
);
}
}
var
decEngineMap
=
make
(
map
[
reflect
.
Type
]
*
decEngine
)
var
decEngineMap
=
make
(
map
[
reflect
.
Type
]
*
decEngine
)
var
decOpMap
=
map
[
int
]
decOp
{
var
decOpMap
=
map
[
reflect
.
Type
]
decOp
{
reflect
.
BoolKind
:
decBool
,
reflect
.
Typeof
((
*
reflect
.
BoolType
)(
nil
))
:
decBool
,
reflect
.
IntKind
:
decInt
,
reflect
.
Typeof
((
*
reflect
.
IntType
)(
nil
))
:
decInt
,
reflect
.
Int8Kind
:
decInt8
,
reflect
.
Typeof
((
*
reflect
.
Int8Type
)(
nil
))
:
decInt8
,
reflect
.
Int16Kind
:
decInt16
,
reflect
.
Typeof
((
*
reflect
.
Int16Type
)(
nil
))
:
decInt16
,
reflect
.
Int32Kind
:
decInt32
,
reflect
.
Typeof
((
*
reflect
.
Int32Type
)(
nil
))
:
decInt32
,
reflect
.
Int64Kind
:
decInt64
,
reflect
.
Typeof
((
*
reflect
.
Int64Type
)(
nil
))
:
decInt64
,
reflect
.
UintKind
:
decUint
,
reflect
.
Typeof
((
*
reflect
.
UintType
)(
nil
))
:
decUint
,
reflect
.
Uint8Kind
:
decUint8
,
reflect
.
Typeof
((
*
reflect
.
Uint8Type
)(
nil
))
:
decUint8
,
reflect
.
Uint16Kind
:
decUint16
,
reflect
.
Typeof
((
*
reflect
.
Uint16Type
)(
nil
))
:
decUint16
,
reflect
.
Uint32Kind
:
decUint32
,
reflect
.
Typeof
((
*
reflect
.
Uint32Type
)(
nil
))
:
decUint32
,
reflect
.
Uint64Kind
:
decUint64
,
reflect
.
Typeof
((
*
reflect
.
Uint64Type
)(
nil
))
:
decUint64
,
reflect
.
FloatKind
:
decFloat
,
reflect
.
Typeof
((
*
reflect
.
FloatType
)(
nil
))
:
decFloat
,
reflect
.
Float32Kind
:
decFloat32
,
reflect
.
Typeof
((
*
reflect
.
Float32Type
)(
nil
))
:
decFloat32
,
reflect
.
Float64Kind
:
decFloat64
,
reflect
.
Typeof
((
*
reflect
.
Float64Type
)(
nil
))
:
decFloat64
,
reflect
.
StringKind
:
decString
,
reflect
.
Typeof
((
*
reflect
.
StringType
)(
nil
))
:
decString
,
}
}
func
getDecEngine
(
rt
reflect
.
Type
)
*
decEngine
func
getDecEngine
(
rt
reflect
.
Type
)
*
decEngine
func
decOpFor
(
typ
reflect
.
Type
)
decOp
{
func
decOpFor
(
typ
reflect
.
Type
)
decOp
{
op
,
ok
:=
decOpMap
[
typ
.
Kind
(
)];
op
,
ok
:=
decOpMap
[
reflect
.
Typeof
(
typ
)];
if
!
ok
{
if
!
ok
{
// Special cases
// Special cases
if
typ
.
Kind
()
==
reflect
.
ArrayKind
{
switch
t
:=
typ
.
(
type
)
{
atyp
:=
typ
.
(
reflect
.
ArrayType
);
case
*
reflect
.
SliceType
:
switch
{
if
_
,
ok
:=
t
.
Elem
()
.
(
*
reflect
.
Uint8Type
);
ok
{
case
atyp
.
Elem
()
.
Kind
()
==
reflect
.
Uint8Kind
:
op
=
decUint8Array
;
op
=
decUint8Array
break
;
case
atyp
.
IsSlice
()
:
elemOp
:=
decOpFor
(
atyp
.
Elem
());
_
,
elemIndir
:=
indirect
(
atyp
.
Elem
());
op
=
func
(
i
*
decInstr
,
state
*
DecState
,
p
unsafe
.
Pointer
)
{
state
.
err
=
decodeSlice
(
atyp
,
state
,
uintptr
(
p
),
elemOp
,
atyp
.
Elem
()
.
Size
(),
i
.
indir
,
elemIndir
);
};
case
!
atyp
.
IsSlice
()
:
elemOp
:=
decOpFor
(
atyp
.
Elem
());
_
,
elemIndir
:=
indirect
(
atyp
.
Elem
());
op
=
func
(
i
*
decInstr
,
state
*
DecState
,
p
unsafe
.
Pointer
)
{
state
.
err
=
decodeArray
(
atyp
,
state
,
uintptr
(
p
),
elemOp
,
atyp
.
Elem
()
.
Size
(),
atyp
.
Len
(),
i
.
indir
,
elemIndir
);
};
}
}
}
elemOp
:=
decOpFor
(
t
.
Elem
());
if
typ
.
Kind
()
==
reflect
.
StructKind
{
_
,
elemIndir
:=
indirect
(
t
.
Elem
());
op
=
func
(
i
*
decInstr
,
state
*
DecState
,
p
unsafe
.
Pointer
)
{
state
.
err
=
decodeSlice
(
t
,
state
,
uintptr
(
p
),
elemOp
,
t
.
Elem
()
.
Size
(),
i
.
indir
,
elemIndir
);
};
case
*
reflect
.
ArrayType
:
elemOp
:=
decOpFor
(
t
.
Elem
());
_
,
elemIndir
:=
indirect
(
t
.
Elem
());
op
=
func
(
i
*
decInstr
,
state
*
DecState
,
p
unsafe
.
Pointer
)
{
state
.
err
=
decodeArray
(
t
,
state
,
uintptr
(
p
),
elemOp
,
t
.
Elem
()
.
Size
(),
t
.
Len
(),
i
.
indir
,
elemIndir
);
};
case
*
reflect
.
StructType
:
// Generate a closure that calls out to the engine for the nested type.
// Generate a closure that calls out to the engine for the nested type.
engine
:=
getDecEngine
(
typ
);
engine
:=
getDecEngine
(
typ
);
styp
:=
typ
.
(
reflect
.
StructType
);
op
=
func
(
i
*
decInstr
,
state
*
DecState
,
p
unsafe
.
Pointer
)
{
op
=
func
(
i
*
decInstr
,
state
*
DecState
,
p
unsafe
.
Pointer
)
{
state
.
err
=
decodeStruct
(
engine
,
styp
,
state
.
r
,
uintptr
(
p
),
i
.
indir
)
state
.
err
=
decodeStruct
(
engine
,
t
,
state
.
r
,
uintptr
(
p
),
i
.
indir
)
};
};
}
}
}
}
...
@@ -427,7 +426,7 @@ func decOpFor(typ reflect.Type) decOp {
...
@@ -427,7 +426,7 @@ func decOpFor(typ reflect.Type) decOp {
}
}
func
compileDec
(
rt
reflect
.
Type
,
typ
Type
)
*
decEngine
{
func
compileDec
(
rt
reflect
.
Type
,
typ
Type
)
*
decEngine
{
srt
,
ok1
:=
rt
.
(
reflect
.
StructType
);
srt
,
ok1
:=
rt
.
(
*
reflect
.
StructType
);
styp
,
ok2
:=
typ
.
(
*
structType
);
styp
,
ok2
:=
typ
.
(
*
structType
);
if
!
ok1
||
!
ok2
{
if
!
ok1
||
!
ok2
{
panicln
(
"TODO: can't handle non-structs"
);
panicln
(
"TODO: can't handle non-structs"
);
...
@@ -438,19 +437,10 @@ func compileDec(rt reflect.Type, typ Type) *decEngine {
...
@@ -438,19 +437,10 @@ func compileDec(rt reflect.Type, typ Type) *decEngine {
field
:=
styp
.
field
[
fieldnum
];
field
:=
styp
.
field
[
fieldnum
];
// TODO(r): verify compatibility with corresponding field of data.
// TODO(r): verify compatibility with corresponding field of data.
// For now, assume perfect correspondence between struct and gob.
// For now, assume perfect correspondence between struct and gob.
_name
,
ftyp
,
_tag
,
offset
:=
srt
.
Field
(
fieldnum
);
f
:=
srt
.
Field
(
fieldnum
);
// How many indirections to the underlying data?
ftyp
,
indir
:=
indirect
(
f
.
Type
);
indir
:=
0
;
for
{
pt
,
ok
:=
ftyp
.
(
reflect
.
PtrType
);
if
!
ok
{
break
}
ftyp
=
pt
.
Sub
();
indir
++
;
}
op
:=
decOpFor
(
ftyp
);
op
:=
decOpFor
(
ftyp
);
engine
.
instr
[
fieldnum
]
=
decInstr
{
op
,
fieldnum
,
indir
,
uintptr
(
o
ffset
)};
engine
.
instr
[
fieldnum
]
=
decInstr
{
op
,
fieldnum
,
indir
,
uintptr
(
f
.
O
ffset
)};
}
}
return
engine
;
return
engine
;
}
}
...
@@ -459,7 +449,8 @@ func compileDec(rt reflect.Type, typ Type) *decEngine {
...
@@ -459,7 +449,8 @@ func compileDec(rt reflect.Type, typ Type) *decEngine {
func
getDecEngine
(
rt
reflect
.
Type
)
*
decEngine
{
func
getDecEngine
(
rt
reflect
.
Type
)
*
decEngine
{
engine
,
ok
:=
decEngineMap
[
rt
];
engine
,
ok
:=
decEngineMap
[
rt
];
if
!
ok
{
if
!
ok
{
return
compileDec
(
rt
,
newType
(
rt
.
Name
(),
rt
));
pkg
,
name
:=
rt
.
Name
();
engine
=
compileDec
(
rt
,
newType
(
name
,
rt
));
decEngineMap
[
rt
]
=
engine
;
decEngineMap
[
rt
]
=
engine
;
}
}
return
engine
;
return
engine
;
...
@@ -472,11 +463,11 @@ func Decode(r io.Reader, e interface{}) os.Error {
...
@@ -472,11 +463,11 @@ func Decode(r io.Reader, e interface{}) os.Error {
for
i
:=
0
;
i
<
indir
;
i
++
{
for
i
:=
0
;
i
<
indir
;
i
++
{
v
=
reflect
.
Indirect
(
v
);
v
=
reflect
.
Indirect
(
v
);
}
}
if
rt
.
Kind
()
!=
reflect
.
StructKind
{
if
_
,
ok
:=
v
.
(
*
reflect
.
StructValue
);
!
ok
{
return
os
.
ErrorString
(
"decode can't handle "
+
rt
.
String
())
return
os
.
ErrorString
(
"decode can't handle "
+
rt
.
String
())
}
}
typeLock
.
Lock
();
typeLock
.
Lock
();
engine
:=
getDecEngine
(
rt
);
engine
:=
getDecEngine
(
rt
);
typeLock
.
Unlock
();
typeLock
.
Unlock
();
return
decodeStruct
(
engine
,
rt
.
(
reflect
.
StructType
),
r
,
uintptr
(
v
.
Addr
()),
0
);
return
decodeStruct
(
engine
,
rt
.
(
*
reflect
.
StructType
),
r
,
uintptr
(
v
.
Addr
()),
0
);
}
}
src/pkg/gob/encode.go
View file @
87783933
...
@@ -14,21 +14,6 @@ import (
...
@@ -14,21 +14,6 @@ import (
"unsafe"
;
"unsafe"
;
)
)
// Step through the indirections on a type to discover the base type.
// Return the number of indirections.
func
indirect
(
t
reflect
.
Type
)
(
rt
reflect
.
Type
,
count
int
)
{
rt
=
t
;
for
{
pt
,
ok
:=
rt
.
(
reflect
.
PtrType
);
if
!
ok
{
break
}
rt
=
pt
.
Sub
();
count
++
;
}
return
;
}
// The global execution state of an instance of the encoder.
// The global execution state of an instance of the encoder.
// Field numbers are delta encoded and always increase. The field
// Field numbers are delta encoded and always increase. The field
// number is initialized to -1 so 0 comes out as delta(1). A delta of
// number is initialized to -1 so 0 comes out as delta(1). A delta of
...
@@ -295,7 +280,7 @@ func encodeStruct(engine *encEngine, w io.Writer, basep uintptr) os.Error {
...
@@ -295,7 +280,7 @@ func encodeStruct(engine *encEngine, w io.Writer, basep uintptr) os.Error {
return
state
.
err
return
state
.
err
}
}
func
encodeArray
(
w
io
.
Writer
,
p
uintptr
,
op
encOp
,
elemWid
int
,
length
int
,
elemIndir
int
)
os
.
Error
{
func
encodeArray
(
w
io
.
Writer
,
p
uintptr
,
op
encOp
,
elemWid
uintptr
,
length
int
,
elemIndir
int
)
os
.
Error
{
state
:=
new
(
EncState
);
state
:=
new
(
EncState
);
state
.
w
=
w
;
state
.
w
=
w
;
state
.
fieldnum
=
-
1
;
state
.
fieldnum
=
-
1
;
...
@@ -316,58 +301,56 @@ func encodeArray(w io.Writer, p uintptr, op encOp, elemWid int, length int, elem
...
@@ -316,58 +301,56 @@ func encodeArray(w io.Writer, p uintptr, op encOp, elemWid int, length int, elem
}
}
var
encEngineMap
=
make
(
map
[
reflect
.
Type
]
*
encEngine
)
var
encEngineMap
=
make
(
map
[
reflect
.
Type
]
*
encEngine
)
var
encOpMap
=
map
[
int
]
encOp
{
var
encOpMap
=
map
[
reflect
.
Type
]
encOp
{
reflect
.
BoolKind
:
encBool
,
reflect
.
Typeof
((
*
reflect
.
BoolType
)(
nil
))
:
encBool
,
reflect
.
IntKind
:
encInt
,
reflect
.
Typeof
((
*
reflect
.
IntType
)(
nil
))
:
encInt
,
reflect
.
Int8Kind
:
encInt8
,
reflect
.
Typeof
((
*
reflect
.
Int8Type
)(
nil
))
:
encInt8
,
reflect
.
Int16Kind
:
encInt16
,
reflect
.
Typeof
((
*
reflect
.
Int16Type
)(
nil
))
:
encInt16
,
reflect
.
Int32Kind
:
encInt32
,
reflect
.
Typeof
((
*
reflect
.
Int32Type
)(
nil
))
:
encInt32
,
reflect
.
Int64Kind
:
encInt64
,
reflect
.
Typeof
((
*
reflect
.
Int64Type
)(
nil
))
:
encInt64
,
reflect
.
UintKind
:
encUint
,
reflect
.
Typeof
((
*
reflect
.
UintType
)(
nil
))
:
encUint
,
reflect
.
Uint8Kind
:
encUint8
,
reflect
.
Typeof
((
*
reflect
.
Uint8Type
)(
nil
))
:
encUint8
,
reflect
.
Uint16Kind
:
encUint16
,
reflect
.
Typeof
((
*
reflect
.
Uint16Type
)(
nil
))
:
encUint16
,
reflect
.
Uint32Kind
:
encUint32
,
reflect
.
Typeof
((
*
reflect
.
Uint32Type
)(
nil
))
:
encUint32
,
reflect
.
Uint64Kind
:
encUint64
,
reflect
.
Typeof
((
*
reflect
.
Uint64Type
)(
nil
))
:
encUint64
,
reflect
.
FloatKind
:
encFloat
,
reflect
.
Typeof
((
*
reflect
.
FloatType
)(
nil
))
:
encFloat
,
reflect
.
Float32Kind
:
encFloat32
,
reflect
.
Typeof
((
*
reflect
.
Float32Type
)(
nil
))
:
encFloat32
,
reflect
.
Float64Kind
:
encFloat64
,
reflect
.
Typeof
((
*
reflect
.
Float64Type
)(
nil
))
:
encFloat64
,
reflect
.
StringKind
:
encString
,
reflect
.
Typeof
((
*
reflect
.
StringType
)(
nil
))
:
encString
,
}
}
func
getEncEngine
(
rt
reflect
.
Type
)
*
encEngine
func
getEncEngine
(
rt
reflect
.
Type
)
*
encEngine
func
encOpFor
(
typ
reflect
.
Type
)
encOp
{
func
encOpFor
(
typ
reflect
.
Type
)
encOp
{
op
,
ok
:=
encOpMap
[
typ
.
Kind
(
)];
op
,
ok
:=
encOpMap
[
reflect
.
Typeof
(
typ
)];
if
!
ok
{
if
!
ok
{
// Special cases
// Special cases
if
typ
.
Kind
()
==
reflect
.
ArrayKind
{
switch
t
:=
typ
.
(
type
)
{
atyp
:=
typ
.
(
reflect
.
ArrayType
);
case
*
reflect
.
SliceType
:
switch
{
if
_
,
ok
:=
t
.
Elem
()
.
(
*
reflect
.
Uint8Type
);
ok
{
case
atyp
.
Elem
()
.
Kind
()
==
reflect
.
Uint8Kind
:
op
=
encUint8Array
;
op
=
encUint8Array
break
;
case
atyp
.
IsSlice
()
:
// Slices have a header; we decode it to find the underlying array.
elemOp
:=
encOpFor
(
atyp
.
Elem
());
_
,
indir
:=
indirect
(
atyp
.
Elem
());
op
=
func
(
i
*
encInstr
,
state
*
EncState
,
p
unsafe
.
Pointer
)
{
slice
:=
*
(
*
reflect
.
SliceHeader
)(
p
);
if
slice
.
Len
==
0
{
return
}
state
.
update
(
i
);
state
.
err
=
encodeArray
(
state
.
w
,
slice
.
Data
,
elemOp
,
atyp
.
Elem
()
.
Size
(),
int
(
slice
.
Len
),
indir
);
};
case
!
atyp
.
IsSlice
()
:
// True arrays have size in the type.
elemOp
:=
encOpFor
(
atyp
.
Elem
());
_
,
indir
:=
indirect
(
atyp
.
Elem
());
op
=
func
(
i
*
encInstr
,
state
*
EncState
,
p
unsafe
.
Pointer
)
{
state
.
update
(
i
);
state
.
err
=
encodeArray
(
state
.
w
,
uintptr
(
p
),
elemOp
,
atyp
.
Elem
()
.
Size
(),
atyp
.
Len
(),
indir
);
};
}
}
}
// Slices have a header; we decode it to find the underlying array.
if
typ
.
Kind
()
==
reflect
.
StructKind
{
elemOp
:=
encOpFor
(
t
.
Elem
());
_
,
indir
:=
indirect
(
t
.
Elem
());
op
=
func
(
i
*
encInstr
,
state
*
EncState
,
p
unsafe
.
Pointer
)
{
slice
:=
(
*
reflect
.
SliceHeader
)(
p
);
if
slice
.
Len
==
0
{
return
}
state
.
update
(
i
);
state
.
err
=
encodeArray
(
state
.
w
,
slice
.
Data
,
elemOp
,
t
.
Elem
()
.
Size
(),
int
(
slice
.
Len
),
indir
);
};
case
*
reflect
.
ArrayType
:
// True arrays have size in the type.
elemOp
:=
encOpFor
(
t
.
Elem
());
_
,
indir
:=
indirect
(
t
.
Elem
());
op
=
func
(
i
*
encInstr
,
state
*
EncState
,
p
unsafe
.
Pointer
)
{
state
.
update
(
i
);
state
.
err
=
encodeArray
(
state
.
w
,
uintptr
(
p
),
elemOp
,
t
.
Elem
()
.
Size
(),
t
.
Len
(),
indir
);
};
case
*
reflect
.
StructType
:
// Generate a closure that calls out to the engine for the nested type.
// Generate a closure that calls out to the engine for the nested type.
engine
:=
getEncEngine
(
typ
);
engine
:=
getEncEngine
(
typ
);
op
=
func
(
i
*
encInstr
,
state
*
EncState
,
p
unsafe
.
Pointer
)
{
op
=
func
(
i
*
encInstr
,
state
*
EncState
,
p
unsafe
.
Pointer
)
{
...
@@ -386,28 +369,19 @@ func encOpFor(typ reflect.Type) encOp {
...
@@ -386,28 +369,19 @@ func encOpFor(typ reflect.Type) encOp {
// it's compatible.
// it's compatible.
// TODO(r): worth checking? typ is unused here.
// TODO(r): worth checking? typ is unused here.
func
compileEnc
(
rt
reflect
.
Type
,
typ
Type
)
*
encEngine
{
func
compileEnc
(
rt
reflect
.
Type
,
typ
Type
)
*
encEngine
{
srt
,
ok
:=
rt
.
(
reflect
.
StructType
);
srt
,
ok
:=
rt
.
(
*
reflect
.
StructType
);
if
!
ok
{
if
!
ok
{
panicln
(
"TODO: can't handle non-structs"
);
panicln
(
"TODO: can't handle non-structs"
);
}
}
engine
:=
new
(
encEngine
);
engine
:=
new
(
encEngine
);
engine
.
instr
=
make
([]
encInstr
,
srt
.
Len
()
+
1
);
// +1 for terminator
engine
.
instr
=
make
([]
encInstr
,
srt
.
NumField
()
+
1
);
// +1 for terminator
for
fieldnum
:=
0
;
fieldnum
<
srt
.
Len
();
fieldnum
++
{
for
fieldnum
:=
0
;
fieldnum
<
srt
.
NumField
();
fieldnum
++
{
_name
,
ftyp
,
_tag
,
offset
:=
srt
.
Field
(
fieldnum
);
f
:=
srt
.
Field
(
fieldnum
);
// How many indirections to the underlying data?
ftyp
,
indir
:=
indirect
(
f
.
Type
);
indir
:=
0
;
for
{
pt
,
ok
:=
ftyp
.
(
reflect
.
PtrType
);
if
!
ok
{
break
}
ftyp
=
pt
.
Sub
();
indir
++
;
}
op
:=
encOpFor
(
ftyp
);
op
:=
encOpFor
(
ftyp
);
engine
.
instr
[
fieldnum
]
=
encInstr
{
op
,
fieldnum
,
indir
,
uintptr
(
o
ffset
)};
engine
.
instr
[
fieldnum
]
=
encInstr
{
op
,
fieldnum
,
indir
,
uintptr
(
f
.
O
ffset
)};
}
}
engine
.
instr
[
srt
.
Len
()]
=
encInstr
{
encStructTerminator
,
0
,
0
,
0
};
engine
.
instr
[
srt
.
NumField
()]
=
encInstr
{
encStructTerminator
,
0
,
0
,
0
};
return
engine
;
return
engine
;
}
}
...
@@ -415,7 +389,8 @@ func compileEnc(rt reflect.Type, typ Type) *encEngine {
...
@@ -415,7 +389,8 @@ func compileEnc(rt reflect.Type, typ Type) *encEngine {
func
getEncEngine
(
rt
reflect
.
Type
)
*
encEngine
{
func
getEncEngine
(
rt
reflect
.
Type
)
*
encEngine
{
engine
,
ok
:=
encEngineMap
[
rt
];
engine
,
ok
:=
encEngineMap
[
rt
];
if
!
ok
{
if
!
ok
{
engine
=
compileEnc
(
rt
,
newType
(
rt
.
Name
(),
rt
));
pkg
,
name
:=
rt
.
Name
();
engine
=
compileEnc
(
rt
,
newType
(
name
,
rt
));
encEngineMap
[
rt
]
=
engine
;
encEngineMap
[
rt
]
=
engine
;
}
}
return
engine
return
engine
...
@@ -428,11 +403,11 @@ func Encode(w io.Writer, e interface{}) os.Error {
...
@@ -428,11 +403,11 @@ func Encode(w io.Writer, e interface{}) os.Error {
for
i
:=
0
;
i
<
indir
;
i
++
{
for
i
:=
0
;
i
<
indir
;
i
++
{
v
=
reflect
.
Indirect
(
v
);
v
=
reflect
.
Indirect
(
v
);
}
}
if
v
.
Kind
()
!=
reflect
.
StructKind
{
if
_
,
ok
:=
v
.
(
*
reflect
.
StructValue
);
!
ok
{
return
os
.
ErrorString
(
"encode can't handle "
+
v
.
Type
()
.
String
())
return
os
.
ErrorString
(
"encode can't handle "
+
v
.
Type
()
.
String
())
}
}
typeLock
.
Lock
();
typeLock
.
Lock
();
engine
:=
getEncEngine
(
rt
);
engine
:=
getEncEngine
(
rt
);
typeLock
.
Unlock
();
typeLock
.
Unlock
();
return
encodeStruct
(
engine
,
w
,
uintptr
(
v
.
(
reflect
.
StructValue
)
.
Addr
()
));
return
encodeStruct
(
engine
,
w
,
v
.
Addr
(
));
}
}
src/pkg/gob/type.go
View file @
87783933
...
@@ -141,50 +141,79 @@ func newStructType(name string) *structType {
...
@@ -141,50 +141,79 @@ func newStructType(name string) *structType {
// Construction
// Construction
func
newType
(
name
string
,
rt
reflect
.
Type
)
Type
func
newType
(
name
string
,
rt
reflect
.
Type
)
Type
// Step through the indirections on a type to discover the base type.
// Return the number of indirections.
func
indirect
(
t
reflect
.
Type
)
(
rt
reflect
.
Type
,
count
int
)
{
rt
=
t
;
for
{
pt
,
ok
:=
rt
.
(
*
reflect
.
PtrType
);
if
!
ok
{
break
;
}
rt
=
pt
.
Elem
();
count
++
;
}
return
;
}
func
newTypeObject
(
name
string
,
rt
reflect
.
Type
)
Type
{
func
newTypeObject
(
name
string
,
rt
reflect
.
Type
)
Type
{
switch
rt
.
Kind
(
)
{
switch
t
:=
rt
.
(
type
)
{
// All basic types are easy: they are predefined.
// All basic types are easy: they are predefined.
case
reflect
.
BoolKind
:
case
*
reflect
.
BoolType
:
return
tBool
return
tBool
case
reflect
.
IntKind
,
reflect
.
Int32Kind
,
reflect
.
Int64Kind
:
case
*
reflect
.
IntType
:
return
tInt
return
tInt
case
reflect
.
UintKind
,
reflect
.
Uint32Kind
,
reflect
.
Uint64Kind
:
case
*
reflect
.
Int32Type
:
return
tInt
case
*
reflect
.
Int64Type
:
return
tInt
case
*
reflect
.
UintType
:
return
tUint
case
*
reflect
.
Uint32Type
:
return
tUint
case
*
reflect
.
Uint64Type
:
return
tUint
return
tUint
case
reflect
.
FloatKind
,
reflect
.
Float32Kind
,
reflect
.
Float64Kind
:
case
*
reflect
.
FloatType
:
return
tFloat
case
*
reflect
.
Float32Type
:
return
tFloat
case
*
reflect
.
Float64Type
:
return
tFloat
return
tFloat
case
reflect
.
StringKind
:
case
*
reflect
.
StringType
:
return
tString
return
tString
case
reflect
.
ArrayKind
:
at
:=
rt
.
(
reflect
.
ArrayType
);
case
*
reflect
.
ArrayType
:
if
at
.
IsSlice
()
{
return
newArrayType
(
name
,
newType
(
""
,
t
.
Elem
()),
t
.
Len
());
// []byte == []uint8 is a special case
if
at
.
Elem
()
.
Kind
()
==
reflect
.
Uint8Kind
{
case
*
reflect
.
SliceType
:
return
tBytes
// []byte == []uint8 is a special case
}
if
_
,
ok
:=
t
.
Elem
()
.
(
*
reflect
.
Uint8Type
);
ok
{
return
newSliceType
(
name
,
newType
(
""
,
at
.
Elem
()));
return
tBytes
}
else
{
return
newArrayType
(
name
,
newType
(
""
,
at
.
Elem
()),
at
.
Len
());
}
}
case
reflect
.
StructKind
:
return
newSliceType
(
name
,
newType
(
""
,
t
.
Elem
()));
case
*
reflect
.
StructType
:
// Install the struct type itself before the fields so recursive
// Install the struct type itself before the fields so recursive
// structures can be constructed safely.
// structures can be constructed safely.
strType
:=
newStructType
(
name
);
strType
:=
newStructType
(
name
);
types
[
rt
]
=
strType
;
types
[
rt
]
=
strType
;
st
:=
rt
.
(
reflect
.
StructType
);
field
:=
make
([]
*
fieldType
,
t
.
NumField
());
field
:=
make
([]
*
fieldType
,
st
.
Len
());
for
i
:=
0
;
i
<
t
.
NumField
();
i
++
{
for
i
:=
0
;
i
<
st
.
Len
();
i
++
{
f
:=
t
.
Field
(
i
);
name
,
typ
,
_tag
,
_offset
:=
st
.
Field
(
i
);
typ
,
_indir
:=
indirect
(
f
.
Type
);
// Find trailing name in type, e.g. from "*gob.Bar" want "Bar", which
_pkg
,
tname
:=
typ
.
Name
();
// is defined as the word after the period (there is at most one period).
if
tname
==
""
{
typestring
:=
typ
.
String
();
tname
=
f
.
Type
.
String
();
period
:=
strings
.
Index
(
typestring
,
"."
);
if
period
>=
0
{
typestring
=
typestring
[
period
+
1
:
len
(
typestring
)]
}
}
field
[
i
]
=
&
fieldType
{
name
,
newType
(
typestring
,
typ
)
};
field
[
i
]
=
&
fieldType
{
f
.
Name
,
newType
(
tname
,
f
.
Type
)
};
}
}
strType
.
field
=
field
;
strType
.
field
=
field
;
return
strType
;
return
strType
;
default
:
default
:
panicln
(
"gob NewTypeObject can't handle type"
,
rt
.
String
());
// TODO(r): panic?
panicln
(
"gob NewTypeObject can't handle type"
,
rt
.
String
());
// TODO(r): panic?
}
}
...
@@ -193,8 +222,12 @@ func newTypeObject(name string, rt reflect.Type) Type {
...
@@ -193,8 +222,12 @@ func newTypeObject(name string, rt reflect.Type) Type {
func
newType
(
name
string
,
rt
reflect
.
Type
)
Type
{
func
newType
(
name
string
,
rt
reflect
.
Type
)
Type
{
// Flatten the data structure by collapsing out pointers
// Flatten the data structure by collapsing out pointers
for
rt
.
Kind
()
==
reflect
.
PtrKind
{
for
{
rt
=
rt
.
(
reflect
.
PtrType
)
.
Sub
();
pt
,
ok
:=
rt
.
(
*
reflect
.
PtrType
);
if
!
ok
{
break
;
}
rt
=
pt
.
Elem
();
}
}
typ
,
present
:=
types
[
rt
];
typ
,
present
:=
types
[
rt
];
if
present
{
if
present
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment