Sign in to follow this  
Rain Dog

Problems registering an array.

Recommended Posts

Using the latest WIP I get an null object reference when attempting to use Deyja's Register Vector class. this is where the error is: asCString::operator const char *() const { if( buffer == 0 ) return ""; return buffer; } It is called in function: GetArrayTypeFromSubType() here. if( sub.GetTokenType() == ttIdentifier ) { // TODO: Improve linear search for( int n = 0; n < arrayTypes.GetLength(); n++ ) { if( arrayTypes[n]->tokenType == ttIdentifier && arrayTypes[n]->name == sub.GetObjectType()->name && ---->>>> This the error line arrayTypes[n]->arrayType == arrayType ) return arrayTypes[n]; } }

Share this post


Link to post
Share on other sites
Would you mind telling me the calls that you do to register the vector? I ask because I have already tested Deyja's Register Vector class (it's part of my regression testing) and it showed no problems.

It may be a special combination of registered types that cause this bug.

Regards,
Andreas

Share this post


Link to post
Share on other sites
It's when i try to register an array of an array of strings.


string[][]


Using the std::string binding that was on the boards here or that comes with AS.


All other primitive data types register just fine. i can do int[], int[][], int[][][]. I did not have a chance to test objects besides string[][]

The problem was introduced sometime between 2.2.1WIP2 and 2.3.0WIP5. I was unable to get and test versions between those releases.
.

[Edited by - Rain Dog on July 10, 2005 11:20:38 PM]

Share this post


Link to post
Share on other sites
OK. I think it is enough for me to find the bug.

What compiler are you using? In MSVC6 there seems to be a bug in std::vector that prohibits registration of vectors of vectors, i.e. int[][]. This may be the reason why I didn't spot this bug.

Regards,
Andreas

Share this post


Link to post
Share on other sites
Alright, I believe I've been able to correct the problem. You'll have to exchange the implementation for asCScriptEngine::RegisterObjectType() and asCScriptEngine::GetArrayTypeFromSubType().


int asCScriptEngine::RegisterObjectType(const char *name, int byteSize, asDWORD flags)
{
// Verify flags
if( flags > 17 )
return ConfigError(asINVALID_ARG);

// Verify type name
if( name == 0 )
return ConfigError(asINVALID_NAME);

// Verify object size (valid sizes 0, 1, 2, or multiple of 4)
if( byteSize < 0 )
return ConfigError(asINVALID_ARG);

if( byteSize < 4 && byteSize == 3 )
return ConfigError(asINVALID_ARG);

if( byteSize > 4 && (byteSize & 0x3) )
return ConfigError(asINVALID_ARG);

// Verify if the name has been registered as a type already
int n;
for( n = 0; n < objectTypes.GetLength(); n++ )
{
if( objectTypes[n]->name == name )
return asALREADY_REGISTERED;
}

for( n = 0; n < arrayTypes.GetLength(); n++ )
{
if( arrayTypes[n]->name == name )
return asALREADY_REGISTERED;
}

// Use builder to parse the datatype
asCDataType dt;
asCBuilder bld(this, 0);
int r = bld.ParseDataType(name, &dt);

// If the builder fails, then the type name
// is new and it should be registered
if( r < 0 )
{
// Make sure the name is not a reserved keyword
asCTokenizer t;
int tokenLen;
int token = t.GetToken(name, strlen(name), &tokenLen);
if( token != ttIdentifier || strlen(name) != (unsigned)tokenLen )
return ConfigError(asINVALID_NAME);

int r = bld.CheckNameConflict(name, 0, 0);
if( r < 0 )
return ConfigError(asNAME_TAKEN);

// Don't have to check against members of object
// types as they are allowed to use the names

// Put the data type in the list
asCObjectType *type = new asCObjectType(this);
type->name = name;
type->tokenType = ttIdentifier;
type->arrayType = 0;
type->size = byteSize;
type->flags = flags;

objectTypes.PushLast(type);
}
else
{
// int[][] must not be allowed to be registered
// if int[] hasn't been registered first
if( dt.GetSubType().IsScriptArray() )
return ConfigError(asLOWER_ARRAY_DIMENSION_NOT_REGISTERED);

if( dt.IsReadOnly() ||
dt.IsReference() )
return ConfigError(asINVALID_TYPE);

// Put the data type in the list
asCObjectType *type = new asCObjectType(this);
type->name = name;
type->subType = dt.GetSubType().GetObjectType();
type->tokenType = dt.GetSubType().GetTokenType();
type->arrayType = dt.GetArrayType();
type->size = byteSize;
type->flags = flags;

arrayTypes.PushLast(type);

// Swap the overloaded type with the script type in arrayTypes
SwapArrayTypes(type, dt.GetObjectType());
}

return asSUCCESS;
}

asCObjectType *asCScriptEngine::GetArrayTypeFromSubType(asCDataType &type)
{
int arrayType = type.GetArrayType();
if( type.IsObjectHandle() )
arrayType = (arrayType<<2) | 3;
else
arrayType = (arrayType<<2) | 2;

// Is there any array type already with this subtype?
if( type.IsObject() )
{
// TODO: Improve linear search
for( int n = 0; n < arrayTypes.GetLength(); n++ )
{
if( arrayTypes[n]->tokenType == ttIdentifier &&
arrayTypes[n]->subType == type.GetObjectType() &&
arrayTypes[n]->arrayType == arrayType )
return arrayTypes[n];
}
}
else
{
// TODO: Improve linear search
for( int n = 0; n < arrayTypes.GetLength(); n++ )
{
if( arrayTypes[n]->tokenType == type.GetTokenType() &&
arrayTypes[n]->arrayType == arrayType )
return arrayTypes[n];
}
}

// No previous array type has been registered

// Create a new array type based on the defaultArrayObjectType
asCObjectType *ot = new asCObjectType(this);
ot->arrayType = arrayType;
ot->flags = asOBJ_CLASS_CDA | asOBJ_SCRIPT_ARRAY;
ot->size = sizeof(asCArrayObject);
ot->name = ""; // Built-in script arrays are registered without name
ot->tokenType = type.GetTokenType();
ot->methods = defaultArrayObjectType->methods;
ot->beh.construct = defaultArrayObjectType->beh.construct;
ot->beh.constructors = defaultArrayObjectType->beh.constructors;
ot->beh.addref = defaultArrayObjectType->beh.addref;
ot->beh.release = defaultArrayObjectType->beh.release;
ot->beh.copy = defaultArrayObjectType->beh.copy;
ot->beh.operators = defaultArrayObjectType->beh.operators;

// The object type needs to store the sub type as well
ot->subType = type.GetObjectType();

// TODO: The indexing behaviour and assignment
// behaviour should use the correct datatype

// Verify if the subtype contains an any object, in which case this array is a potential circular reference
if( ot->subType && (ot->subType->flags & asOBJ_CONTAINS_ANY) )
ot->flags |= asOBJ_POTENTIAL_CIRCLE | asOBJ_CONTAINS_ANY;

arrayTypes.PushLast(ot);

// We need to store the object type somewhere for clean-up later
scriptArrayTypes.PushLast(ot);

ot->refCount++;

return ot;
}




I had messed up the registration of multi-dimensional arrays with the latest changes, and I didn't have any test cases for this scenario. Now I do, thanks to you. :)

Let me know if there is any more problems with the latest version.

Regards,
Andreas

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this