Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F622493
general_states.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
19 KB
Referenced Files
None
Subscribers
None
general_states.cpp
View Options
#include
"general_states.h"
#include
"str_util.h"
#include
"main/logging.h"
#include
"compat/misc.h"
#include
"util/locked_type.h"
#include
"util/lockless_type.h"
#include
"obj/object.h"
#include
"obj/blueprint.h"
#include
<cstring>
#include
<vector>
#include
<string>
#include
<fstream>
#include
<unordered_map>
#include
<unordered_set>
#include
"network.h"
#include
"empire.h"
#include
"scripts/script_components.h"
#include
"scripts/generic_call.h"
StateDefinition
errorStateDefinition
;
std
::
unordered_map
<
std
::
string
,
StateDefinition
*>
definitions
;
std
::
vector
<
StateDefinition
*>
stateDefinitions
;
template
<
class
T
>
void
copySimple
(
void
*
dest
,
void
*
src
)
{
if
(
src
)
*
(
T
*
)
dest
=
*
(
T
*
)
src
;
else
new
(
dest
)
T
();
}
template
<
class
T
>
void
*
parseNumber
(
const
std
::
string
&
str
)
{
return
(
void
*
)
new
T
(
toNumber
<
T
>
(
str
));
}
template
<
class
T
>
void
defaultConstruct
(
void
*
dest
,
void
*
src
)
{
new
(
dest
)
T
();
}
template
<
class
T
>
void
destruct
(
void
*
mem
)
{
if
(
mem
)
((
T
*
)
mem
)
->~
T
();
}
template
<
class
T
>
void
defaultWrite
(
net
::
Message
&
msg
,
void
*
mem
)
{
msg
<<
*
(
T
*
)
mem
;
}
template
<
class
T
>
void
defaultRead
(
net
::
Message
&
msg
,
void
*
mem
)
{
msg
>>
*
(
T
*
)
mem
;
}
//In bind_network.cpp
namespace
scripts
{
extern
net
::
Message
&
readObjectScr
(
net
::
Message
&
msg
,
Object
**
obj
);
extern
net
::
Message
&
writeObjectScr
(
net
::
Message
&
msg
,
Object
*
obj
);
extern
net
::
Message
&
readEmpire
(
net
::
Message
&
msg
,
Empire
**
emp
);
extern
net
::
Message
&
writeEmpire
(
net
::
Message
&
msg
,
Empire
*
emp
);
};
std
::
unordered_map
<
std
::
string
,
StateValueDefinition
>
stateValueTypes
;
void
resetStateValueTypes
()
{
stateValueTypes
.
clear
();
stateValueTypes
[
"int"
].
setup
(
sizeof
(
int
),
"int"
,
copySimple
<
int
>
,
parseNumber
<
int
>
,
nullptr
,
defaultWrite
<
int
>
,
defaultRead
<
int
>
,
[](
asIScriptGeneric
*
f
,
void
*
mem
)
{
if
(
mem
)
f
->
SetReturnDWord
(
*
(
asDWORD
*
)
mem
);
else
f
->
SetReturnDWord
((
asDWORD
)
0
);
});
stateValueTypes
[
"uint"
].
setup
(
sizeof
(
unsigned
),
"uint"
,
copySimple
<
unsigned
>
,
parseNumber
<
unsigned
>
,
nullptr
,
defaultWrite
<
unsigned
>
,
defaultRead
<
unsigned
>
,
[](
asIScriptGeneric
*
f
,
void
*
mem
)
{
if
(
mem
)
f
->
SetReturnDWord
(
*
(
asDWORD
*
)
mem
);
else
f
->
SetReturnDWord
((
asDWORD
)
0
);
});
stateValueTypes
[
"double"
].
setup
(
sizeof
(
double
),
"double"
,
copySimple
<
double
>
,
parseNumber
<
double
>
,
nullptr
,
defaultWrite
<
double
>
,
defaultRead
<
double
>
,
[](
asIScriptGeneric
*
f
,
void
*
mem
)
{
if
(
mem
)
f
->
SetReturnDouble
(
*
(
double
*
)
mem
);
else
f
->
SetReturnDouble
((
double
)
0.0
);
});
stateValueTypes
[
"float"
].
setup
(
sizeof
(
double
),
"float"
,
copySimple
<
float
>
,
parseNumber
<
float
>
,
nullptr
,
defaultWrite
<
float
>
,
defaultRead
<
float
>
,
[](
asIScriptGeneric
*
f
,
void
*
mem
)
{
if
(
mem
)
f
->
SetReturnDouble
(
*
(
float
*
)
mem
);
else
f
->
SetReturnDouble
((
float
)
0.0
);
});
stateValueTypes
[
"bool"
].
setup
(
sizeof
(
bool
),
"bool"
,
copySimple
<
bool
>
,
[](
const
std
::
string
&
str
)
->
void
*
{
return
new
bool
(
toBool
(
str
));
},
nullptr
,
defaultWrite
<
bool
>
,
defaultRead
<
bool
>
,
[
&
](
asIScriptGeneric
*
f
,
void
*
mem
)
{
if
(
mem
)
f
->
SetReturnByte
(
*
(
bool
*
)
mem
);
else
f
->
SetReturnByte
(
false
);
});
stateValueTypes
[
"locked_int"
].
setup
(
sizeof
(
LocklessInt
),
"locked_int"
,
[](
void
*
dest
,
void
*
src
)
{
if
(
src
)
new
(
dest
)
LocklessInt
(
*
(
LocklessInt
*
)
src
);
else
new
(
dest
)
LocklessInt
();
},
[](
const
std
::
string
&
str
)
->
void
*
{
return
new
LocklessInt
(
toNumber
<
int
>
(
str
));
},
[](
void
*
memory
)
{
((
LocklessInt
*
)
memory
)
->~
LocklessInt
();
},
[](
net
::
Message
&
msg
,
void
*
mem
)
{
msg
<<
((
LocklessInt
*
)
mem
)
->
value
;
},
[](
net
::
Message
&
msg
,
void
*
mem
)
{
msg
>>
((
LocklessInt
*
)
mem
)
->
value
;
},
[](
asIScriptGeneric
*
f
,
void
*
mem
)
{
f
->
SetReturnObject
(
mem
);
});
stateValueTypes
[
"locked_double"
].
setup
(
sizeof
(
LocklessDouble
),
"locked_double"
,
[](
void
*
dest
,
void
*
src
)
{
if
(
src
)
new
(
dest
)
LocklessDouble
(
*
(
LocklessDouble
*
)
src
);
else
new
(
dest
)
LocklessDouble
();
},
[](
const
std
::
string
&
str
)
->
void
*
{
return
new
LocklessDouble
(
toNumber
<
double
>
(
str
));
},
[](
void
*
memory
)
{
((
LocklessDouble
*
)
memory
)
->~
LocklessDouble
();
},
[](
net
::
Message
&
msg
,
void
*
mem
)
{
msg
<<
((
LocklessDouble
*
)
mem
)
->
value
;
},
[](
net
::
Message
&
msg
,
void
*
mem
)
{
msg
>>
((
LocklessDouble
*
)
mem
)
->
value
;
},
[](
asIScriptGeneric
*
f
,
void
*
mem
)
{
f
->
SetReturnObject
(
mem
);
});
//TODO: Support default initialization
stateValueTypes
[
"vec3d"
].
setup
(
sizeof
(
vec3d
),
"vec3d"
,
copySimple
<
vec3d
>
,
nullptr
);
stateValueTypes
[
"quaterniond"
].
setup
(
sizeof
(
quaterniond
),
"quaterniond"
,
copySimple
<
quaterniond
>
,
nullptr
);
stateValueTypes
[
"string"
].
setup
(
sizeof
(
std
::
string
),
"string"
,
[](
void
*
dest
,
void
*
src
)
{
if
(
src
)
new
(
dest
)
std
::
string
(
*
(
std
::
string
*
)
src
);
else
new
(
dest
)
std
::
string
();
},
[](
const
std
::
string
&
str
)
->
void
*
{
return
new
std
::
string
(
str
);
},
[](
void
*
mem
)
{
((
std
::
string
*
)
mem
)
->~
basic_string
();
}
);
stateValueTypes
[
"Empire"
].
setup
(
sizeof
(
Empire
*
),
"Empire@"
,
copySimple
<
Empire
*>
,
nullptr
,
nullptr
,
[](
net
::
Message
&
msg
,
void
*
mem
)
{
scripts
::
writeEmpire
(
msg
,
*
(
Empire
**
)
mem
);
},
[](
net
::
Message
&
msg
,
void
*
mem
)
{
scripts
::
readEmpire
(
msg
,
(
Empire
**
)
mem
);
},
[](
asIScriptGeneric
*
f
,
void
*
mem
)
{
if
(
mem
)
{
Empire
*
emp
=
*
(
Empire
**
)
mem
;
f
->
SetReturnAddress
(
emp
);
}
else
{
f
->
SetReturnAddress
(
nullptr
);
}
});
stateValueTypes
[
"Object$"
].
setup
(
sizeof
(
Object
*
),
"Object@"
,
[](
void
*
dest
,
void
*
src
)
{
Object
*&
d
=
*
(
Object
**
)
dest
;
if
(
src
)
{
Object
*
s
=
*
(
Object
**
)
src
;
if
(
s
)
s
->
grab
();
if
(
d
)
d
->
drop
();
d
=
s
;
}
else
{
if
(
d
)
d
->
drop
();
d
=
0
;
}
},
nullptr
,
//Object@ cannot have a default value
[](
void
*
mem
)
{
Object
*
obj
=
*
(
Object
**
)
mem
;
if
(
obj
)
obj
->
drop
();
},
[](
net
::
Message
&
msg
,
void
*
mem
)
{
scripts
::
writeObjectScr
(
msg
,
*
(
Object
**
)
mem
);
},
[](
net
::
Message
&
msg
,
void
*
mem
)
{
scripts
::
readObjectScr
(
msg
,
(
Object
**
)
mem
);
},
[](
asIScriptGeneric
*
f
,
void
*
mem
)
{
if
(
mem
)
{
Object
*
obj
=
*
(
Object
**
)
mem
;
if
(
obj
)
obj
->
grab
();
f
->
SetReturnAddress
(
obj
);
}
else
{
f
->
SetReturnAddress
(
nullptr
);
}
},
[](
void
*
mem
)
{
Object
*
obj
=
*
(
Object
**
)
mem
;
if
(
obj
)
{
obj
->
drop
();
*
(
void
**
)
mem
=
nullptr
;
}
});
stateValueTypes
[
"Object"
].
setup
(
sizeof
(
LockedHandle
<
Object
>
),
"Object@"
,
[](
void
*
dest
,
void
*
src
)
{
if
(
src
)
new
(
dest
)
LockedHandle
<
Object
>
(
*
(
LockedHandle
<
Object
>*
)
src
);
else
new
(
dest
)
LockedHandle
<
Object
>
();
},
nullptr
,
//Object@ cannot have a default value
[](
void
*
mem
)
{
((
LockedHandle
<
Object
>*
)
mem
)
->~
LockedHandle
();
},
[](
net
::
Message
&
msg
,
void
*
mem
)
{
Object
*
obj
=
((
LockedHandle
<
Object
>*
)
mem
)
->
get
();
scripts
::
writeObjectScr
(
msg
,
obj
);
if
(
obj
)
obj
->
drop
();
},
[](
net
::
Message
&
msg
,
void
*
mem
)
{
Object
*
obj
=
nullptr
;
scripts
::
readObjectScr
(
msg
,
&
obj
);
((
LockedHandle
<
Object
>*
)
mem
)
->
set
(
obj
);
if
(
obj
)
obj
->
drop
();
},
[](
asIScriptGeneric
*
f
,
void
*
mem
)
{
Object
*
obj
=
((
LockedHandle
<
Object
>*
)
mem
)
->
get
();
f
->
SetReturnAddress
(
obj
);
},
[](
void
*
mem
)
{
((
LockedHandle
<
Object
>*
)
mem
)
->
set
(
nullptr
);
},
[](
asIScriptGeneric
*
f
,
void
*
mem
)
{
Object
*
obj
=
(
Object
*
)
f
->
GetArgAddress
(
0
);
((
LockedHandle
<
Object
>*
)
mem
)
->
set
(
obj
);
});
stateValueTypes
[
"Object"
].
returnType
=
"Object@"
;
stateValueTypes
[
"Blueprint"
].
setup
(
sizeof
(
Blueprint
),
"Blueprint"
,
defaultConstruct
<
Blueprint
>
,
nullptr
,
destruct
<
Blueprint
>
,
nullptr
,
nullptr
,
[](
asIScriptGeneric
*
f
,
void
*
mem
)
{
f
->
SetReturnAddress
(
mem
);
},
[](
void
*
mem
)
{
Blueprint
*
bp
=
(
Blueprint
*
)
mem
;
if
(
bp
)
bp
->
preClear
();
});
stateValueTypes
[
"Blueprint"
].
returnType
=
"Blueprint@"
;
}
void
StateValueDefinition::setup
(
unsigned
Size
,
std
::
string
Type
,
decltype
(
init
)
Init
,
decltype
(
parser
)
Parse
,
decltype
(
clear
)
Clear
,
decltype
(
writeSync
)
Write
,
decltype
(
readSync
)
Read
,
decltype
(
returnFunc
)
Return
,
decltype
(
clearRefs
)
ClearRefs
,
decltype
(
paramSetFunc
)
ParamSet
)
{
size
=
Size
;
type
=
Type
;
init
=
Init
;
parser
=
Parse
;
clear
=
Clear
;
writeSync
=
Write
;
readSync
=
Read
;
returnFunc
=
Return
;
clearRefs
=
ClearRefs
;
paramSetFunc
=
ParamSet
;
//Align to the size of the largest primitve that could fit into the type
if
(
size
>=
sizeof
(
void
*
))
alignment
=
sizeof
(
void
*
);
else
if
(
size
>=
4
)
alignment
=
4
;
else
if
(
size
>=
2
)
alignment
=
2
;
else
alignment
=
1
;
}
void
*
StateValueDefinition::parse
(
const
std
::
string
&
str
)
const
{
if
(
parser
)
return
parser
(
str
);
else
return
0
;
}
void
StateValueDefinition::alloc
(
void
*
memory
,
void
*
arg
)
const
{
memset
(
memory
,
0
,
size
);
if
(
init
)
init
(
memory
,
arg
);
}
void
StateValueDefinition::free
(
void
*
memory
)
const
{
if
(
clear
)
clear
(
memory
);
}
void
StateValueDefinition::preClear
(
void
*
memory
)
const
{
if
(
clearRefs
)
clearRefs
(
memory
);
}
bool
StateValueDefinition::syncable
()
const
{
return
writeSync
!=
0
&&
readSync
!=
0
;
}
bool
StateValueDefinition::returnable
()
const
{
return
returnFunc
!=
0
;
}
void
StateValueDefinition::syncWrite
(
net
::
Message
&
file
,
void
*
memory
)
const
{
if
(
writeSync
)
writeSync
(
file
,
memory
);
}
void
StateValueDefinition::syncRead
(
net
::
Message
&
file
,
void
*
memory
)
const
{
if
(
readSync
)
readSync
(
file
,
memory
);
}
void
StateValueDefinition::setReturn
(
asIScriptGeneric
*
gen
,
void
*
memory
)
const
{
if
(
returnFunc
)
returnFunc
(
gen
,
memory
);
}
bool
StateValueDefinition::isParam
()
const
{
return
(
bool
)
paramSetFunc
;
}
void
StateValueDefinition::setFromParam
(
asIScriptGeneric
*
gen
,
void
*
memory
)
const
{
if
(
paramSetFunc
)
paramSetFunc
(
gen
,
memory
);
}
const
StateValueDefinition
*
getStateValueType
(
const
std
::
string
&
type
)
{
auto
iter
=
stateValueTypes
.
find
(
type
);
if
(
iter
!=
stateValueTypes
.
end
())
return
&
iter
->
second
;
return
0
;
}
void
clearStateDefinitions
()
{
foreach
(
it
,
definitions
)
delete
it
->
second
;
definitions
.
clear
();
stateDefinitions
.
clear
();
}
void
loadStateDefinitions
(
const
std
::
string
&
filename
,
const
std
::
string
&
sharedBase
)
{
StateDefinition
*
def
=
nullptr
;
std
::
unordered_set
<
std
::
string
>
used_names
;
scripts
::
MethodFlags
flags
;
flags
.
restricted
=
true
;
auto
finishDefinition
=
[
&
def
,
&
used_names
,
&
flags
]()
{
if
(
def
==
nullptr
)
return
;
definitions
[
def
->
name
]
=
def
;
stateDefinitions
.
push_back
(
def
);
StateDefinition
*
type
=
def
;
def
->
asVar
.
setup
(
def
->
totalDataSize
,
def
->
name
.
c_str
(),
[
type
](
void
*
dest
,
void
*
src
)
{
if
(
src
)
type
->
copy
(
dest
,
src
);
else
type
->
prepare
(
dest
);
},
nullptr
,
[
type
](
void
*
mem
)
{
type
->
unprepare
(
mem
);
});
used_names
.
clear
();
def
=
nullptr
;
flags
.
reset
();
flags
.
restricted
=
true
;
};
std
::
ifstream
file
(
filename
);
if
(
!
file
.
is_open
())
{
error
(
"Could not open '%s'"
,
filename
.
c_str
());
return
;
}
skipBOM
(
file
);
bool
inType
=
false
;
char
name
[
81
],
dtype
[
25
],
value
[
81
];
char
bracket
,
bracket2
;
while
(
true
)
{
std
::
string
line
;
std
::
getline
(
file
,
line
);
if
(
file
.
fail
())
break
;
std
::
string
parse
=
line
.
substr
(
0
,
line
.
find
(
"//"
));
if
(
parse
.
find_first_not_of
(
"
\t\n\r
"
)
==
std
::
string
::
npos
)
continue
;
if
(
!
inType
)
{
finishDefinition
();
int
args
=
sscanf
(
parse
.
c_str
(),
" %80s %c %80s %c"
,
name
,
&
bracket
,
value
,
&
bracket2
);
if
((
args
!=
2
&&
args
!=
4
)
||
(
args
==
2
&&
bracket
!=
'{'
)
||
(
args
==
4
&&
(
bracket
!=
':'
||
bracket2
!=
'{'
)))
{
error
(
"Unrecognized line '%s'"
,
line
.
c_str
());
continue
;
}
std
::
string
typeName
=
name
;
auto
previous
=
definitions
.
find
(
typeName
);
if
(
previous
!=
definitions
.
end
())
{
error
(
"Duplicate type '%s'"
,
name
);
continue
;
}
auto
baseType
=
definitions
.
find
(
sharedBase
);
if
(
baseType
==
definitions
.
end
())
{
if
(
!
sharedBase
.
empty
()
&&
sharedBase
!=
name
)
error
(
"Expected definition of base type '%s'"
,
sharedBase
.
c_str
());
def
=
new
StateDefinition
();
}
else
{
def
=
new
StateDefinition
(
*
baseType
->
second
);
}
if
(
args
==
4
)
def
->
scriptClass
=
value
;
used_names
.
clear
();
def
->
name
=
name
;
inType
=
true
;
}
else
if
(
def
)
{
//Parse flag lines (e.g. restricted:)
std
::
string
trimmed
=
trim
(
parse
);
if
(
!
trimmed
.
empty
()
&&
trimmed
.
back
()
==
':'
)
{
trimmed
.
back
()
=
' '
;
flags
.
reset
();
flags
.
parse
(
trimmed
);
continue
;
}
int
args
=
sscanf
(
parse
.
c_str
(),
" %c"
,
&
bracket
);
if
(
args
==
1
&&
bracket
==
'}'
)
{
inType
=
false
;
continue
;
}
parse
=
trimmed
;
//Parse methods
if
(
parse
.
find
(
'('
)
!=
std
::
string
::
npos
)
{
StateDefinition
::
method
method
;
method
.
flags
=
flags
;
method
.
flags
.
parse
(
parse
);
method
.
decl
=
parse
;
method
.
wrapped
=
nullptr
;
def
->
methods
.
push_back
(
method
);
continue
;
}
bool
synced
=
false
;
if
(
parse
.
compare
(
0
,
7
,
"synced "
)
==
0
)
{
parse
=
parse
.
substr
(
7
);
synced
=
true
;
}
bool
attribute
=
false
;
if
(
parse
.
compare
(
0
,
10
,
"attribute "
)
==
0
)
{
parse
=
parse
.
substr
(
10
);
attribute
=
true
;
}
args
=
sscanf
(
parse
.
c_str
(),
" %24s %80s = %80s"
,
dtype
,
name
,
value
);
if
(
args
<
2
)
{
error
(
"Unrecognized line '%s'"
,
line
.
c_str
());
continue
;
}
if
(
args
<
3
)
value
[
0
]
=
'\0'
;
if
(
used_names
.
find
(
name
)
!=
used_names
.
end
())
{
error
(
"Duplicate member '%s'"
,
name
);
continue
;
}
if
(
!
isIdentifier
(
name
))
{
error
(
"'%s' is not a valid identifier"
,
name
);
continue
;
}
StateDefinition
::
stateDefMember
mem
;
mem
.
name
=
name
;
mem
.
defText
=
value
;
mem
.
typeName
=
dtype
;
mem
.
synced
=
synced
;
mem
.
attribute
=
attribute
;
if
(
flags
.
restricted
)
mem
.
access
=
SR_Restricted
;
else
if
(
flags
.
visible
)
mem
.
access
=
SR_Visible
;
else
mem
.
access
=
SR_Invisible
;
def
->
types
.
push_back
(
mem
);
}
else
{
if
(
parse
.
find
(
'}'
)
!=
std
::
string
::
npos
)
inType
=
false
;
}
}
finishDefinition
();
}
void
finalizeStateDefinitions
()
{
for
(
auto
i
=
stateDefinitions
.
begin
(),
end
=
stateDefinitions
.
end
();
i
!=
end
;
++
i
)
{
auto
&
def
=
**
i
;
unsigned
offset
=
0
;
//Determine data types of all members
for
(
auto
t
=
def
.
types
.
begin
(),
tend
=
def
.
types
.
end
();
t
!=
tend
;)
{
auto
&
member
=
*
t
;
const
StateValueDefinition
*
valueType
=
getStateValueType
(
member
.
typeName
);
if
(
valueType
==
0
||
(
member
.
synced
&&
!
valueType
->
syncable
()))
{
if
(
valueType
)
error
(
"%s error: Type '%s' for member '%s' cannot be synced"
,
def
.
name
.
c_str
(),
member
.
typeName
.
c_str
(),
member
.
name
.
c_str
());
else
error
(
"%s error: Unknown type '%s' for member '%s'"
,
def
.
name
.
c_str
(),
member
.
typeName
.
c_str
(),
member
.
name
.
c_str
());
t
=
def
.
types
.
erase
(
t
);
tend
=
def
.
types
.
end
();
continue
;
}
member
.
def
=
valueType
;
member
.
defaultValue
=
valueType
->
parse
(
member
.
defText
);
if
(
offset
&
(
valueType
->
alignment
-
1
))
{
offset
&=
~
(
unsigned
)(
valueType
->
alignment
-
1
);
offset
+=
(
unsigned
)
valueType
->
alignment
;
}
member
.
offset
=
offset
;
offset
+=
valueType
->
size
;
++
t
;
}
def
.
totalDataSize
=
offset
;
//Parse through methods
unsigned
methodIndex
=
0
;
for
(
auto
m
=
def
.
methods
.
begin
(),
mend
=
def
.
methods
.
end
();
m
!=
mend
;
++
m
,
++
methodIndex
)
{
auto
&
method
=
*
m
;
scripts
::
GenericCallDesc
desc
;
if
(
method
.
flags
.
server
||
method
.
flags
.
shadow
)
desc
.
parse
(
method
.
decl
,
true
,
true
);
else
desc
.
parse
(
method
.
decl
,
true
,
false
);
if
(
!
method
.
flags
.
local
&&
desc
.
returnType
.
type
)
{
error
(
"Error: '%s': non-local function cannot return a value."
,
method
.
decl
.
c_str
());
continue
;
}
else
if
(
desc
.
returnType
==
scripts
::
GT_Custom_Handle
)
{
error
(
"Error: '%s': script types cannot be return values."
,
method
.
decl
.
c_str
());
continue
;
}
scripts
::
WrappedMethod
*
wm
=
new
scripts
::
WrappedMethod
();
wm
->
fullDeclaration
=
method
.
decl
;
wm
->
index
=
methodIndex
;
wm
->
local
=
method
.
flags
.
local
;
wm
->
server
=
method
.
flags
.
server
;
wm
->
shadow
=
method
.
flags
.
shadow
;
wm
->
wrapped
=
desc
;
wm
->
restricted
=
method
.
flags
.
restricted
;
wm
->
async
=
method
.
flags
.
async
;
wm
->
safe
=
method
.
flags
.
safe
;
wm
->
relocking
=
method
.
flags
.
relocking
;
wm
->
isComponentMethod
=
false
;
if
(
wm
->
wrapped
.
returnsArray
)
{
wm
->
wrapped
.
returnType
.
type
=
scripts
::
GT_Custom_Handle
;
wm
->
wrapped
.
returnType
.
customName
=
"DataList"
;
}
wm
->
desc
.
append
(
desc
);
wm
->
desc
.
name
=
desc
.
name
;
wm
->
desc
.
constFunction
=
false
;
wm
->
desc
.
returnType
=
desc
.
returnType
;
wm
->
desc
.
returnsArray
=
wm
->
wrapped
.
returnsArray
;
method
.
wrapped
=
wm
;
}
}
}
StateDefinition
::
StateDefinition
()
:
totalDataSize
(
0
),
base
(
0
)
{}
StateDefinition
::
StateDefinition
(
const
StateDefinition
&
other
)
:
types
(
other
.
types
),
totalDataSize
(
other
.
totalDataSize
),
base
(
&
other
),
methods
(
other
.
methods
)
{
//TODO: default args are not deleted, so we'll just copy the pointers blindly for now
}
StateDefinition
::~
StateDefinition
()
{
//TODO: default args are not yet deleted, see above
}
void
StateDefinition
::
align
(
unsigned
&
offset
)
{
unsigned
off
=
offset
%
sizeof
(
void
*
);
if
(
off
!=
0
)
offset
+=
sizeof
(
void
*
)
-
off
;
}
void
StateDefinition
::
align
(
void
*&
memory
)
{
size_t
off
=
(
size_t
)
memory
%
sizeof
(
void
*
);
if
(
off
!=
0
)
memory
=
(
char
*
)
memory
+
(
sizeof
(
void
*
)
-
off
);
}
const
StateDefinition
&
getStateDefinition
(
const
std
::
string
&
name
)
{
auto
it
=
definitions
.
find
(
name
);
if
(
it
==
definitions
.
end
())
return
errorStateDefinition
;
return
*
it
->
second
;
}
unsigned
StateDefinition
::
getSize
(
unsigned
atOffset
)
const
{
unsigned
off
=
atOffset
%
sizeof
(
void
*
);
if
(
off
==
0
)
return
totalDataSize
;
else
return
totalDataSize
+
(
sizeof
(
void
*
)
-
off
);
}
void
StateDefinition
::
prepare
(
void
*&
memory
)
const
{
align
(
memory
);
char
*
data
=
(
char
*
)
memory
;
for
(
auto
v
=
types
.
begin
(),
end
=
types
.
end
();
v
!=
end
;
++
v
)
{
auto
&
type
=
*
v
->
def
;
type
.
alloc
(
data
+
v
->
offset
,
v
->
defaultValue
);
}
memory
=
data
+
totalDataSize
;
}
void
StateDefinition
::
copy
(
void
*&
memory
,
void
*&
from
)
const
{
align
(
memory
);
align
(
from
);
char
*
data
=
(
char
*
)
memory
,
*
source
=
(
char
*
)
from
;
for
(
auto
v
=
types
.
begin
(),
end
=
types
.
end
();
v
!=
end
;
++
v
)
{
auto
&
type
=
*
v
->
def
;
type
.
alloc
(
data
+
v
->
offset
,
source
+
v
->
offset
);
}
memory
=
data
+
totalDataSize
;
from
=
source
+
totalDataSize
;
}
void
StateDefinition
::
preClear
(
void
*&
memory
)
const
{
align
(
memory
);
char
*
data
=
(
char
*
)
memory
;
for
(
auto
v
=
types
.
begin
(),
end
=
types
.
end
();
v
!=
end
;
++
v
)
{
auto
&
type
=
*
v
->
def
;
type
.
preClear
(
data
+
v
->
offset
);
}
memory
=
data
+
totalDataSize
;
}
void
StateDefinition
::
unprepare
(
void
*&
memory
)
const
{
align
(
memory
);
char
*
data
=
(
char
*
)
memory
;
for
(
auto
v
=
types
.
begin
(),
end
=
types
.
end
();
v
!=
end
;
++
v
)
{
auto
&
type
=
*
v
->
def
;
type
.
free
(
data
+
v
->
offset
);
}
memory
=
data
+
totalDataSize
;
}
void
StateDefinition
::
syncWrite
(
net
::
Message
&
msg
,
void
*
memory
)
const
{
align
(
memory
);
char
*
data
=
(
char
*
)
memory
;
for
(
auto
i
=
types
.
begin
(),
end
=
types
.
end
();
i
!=
end
;
++
i
)
{
auto
&
state
=
*
i
->
def
;
if
(
i
->
synced
)
state
.
syncWrite
(
msg
,
data
+
i
->
offset
);
}
}
void
StateDefinition
::
syncRead
(
net
::
Message
&
msg
,
void
*
memory
)
const
{
align
(
memory
);
char
*
data
=
(
char
*
)
memory
;
for
(
auto
i
=
types
.
begin
(),
end
=
types
.
end
();
i
!=
end
;
++
i
)
{
auto
&
state
=
*
i
->
def
;
if
(
i
->
synced
)
state
.
syncRead
(
msg
,
data
+
i
->
offset
);
}
}
StateList
::
StateList
()
:
def
(
&
errorStateDefinition
),
values
(
0
)
{
}
StateList
::
StateList
(
const
StateDefinition
&
Def
)
:
def
(
0
),
values
(
0
)
{
change
(
Def
);
}
StateList
::~
StateList
()
{
clear
();
}
void
StateList
::
change
(
const
StateDefinition
&
Def
)
{
clear
();
def
=
&
Def
;
if
(
def
->
totalDataSize
==
0
)
return
;
values
=
new
char
[
def
->
totalDataSize
];
void
*
mem
=
values
;
def
->
prepare
(
mem
);
}
void
StateList
::
clear
()
{
if
(
values
)
{
void
*
mem
=
values
;
def
->
unprepare
(
mem
);
delete
[]
values
;
values
=
0
;
}
def
=
0
;
}
StateList
&
StateList
::
operator
=
(
StateList
&
other
)
{
clear
();
def
=
other
.
def
;
if
(
def
==
0
)
return
*
this
;
values
=
new
char
[
def
->
totalDataSize
];
void
*
mem
=
values
,
*
otherMem
=
other
.
values
;;
def
->
copy
(
mem
,
otherMem
);
return
*
this
;
}
unsigned
StateList
::
count
()
const
{
return
(
unsigned
)
def
->
types
.
size
();
}
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sat, Nov 14, 8:14 PM (23 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
140376
Default Alt Text
general_states.cpp (19 KB)
Attached To
Mode
R80 StarRuler2-Source
Attached
Detach File
Event Timeline