Sign in to follow this  

Problems registering an array.

This topic is 4573 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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
Ok, I'll get back with you on it a little later. I'm inspecting what builds it started in.

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
Sign in to follow this