Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate CDataPack from a Compact Cassette tape. #688

Merged
merged 5 commits into from Dec 30, 2017
Merged

Migrate CDataPack from a Compact Cassette tape. #688

merged 5 commits into from Dec 30, 2017

Conversation

KyleSanderson
Copy link
Member

@KyleSanderson KyleSanderson commented Sep 19, 2017

This lift and shifts CDataPack from a linear datatype to something using a vector with type mixed in. Iterators will change (again), so plugins manually using SetPackPosition without ReadPackPosition (against the API) will experience breakage; if this even builds.

@Headline
Copy link
Member

@Headline Headline commented Sep 20, 2017

Floats seem to show 0.0 on ReadFloat.

public void OnPluginStart()
{
	int integer = 32;
	float floatingPoint = 32.0;
	char[] string = "Hello.";
	
	DataPack pack = new DataPack();
	
	pack.WriteCell(integer);
	pack.WriteFloat(floatingPoint);
	pack.WriteString(string);
	
	DataPackPos pos = pack.Position;
	
	pack.Reset();
	
	int integer2;
	float floatingPoint2;
	char string2[8];
	
	integer2 = pack.ReadCell();
	floatingPoint2 = pack.ReadFloat();
	pack.ReadString(string2, sizeof(string2));
	
	PrintToServer("int: %i, float: %.2f, string: %s, pos: %i",
					integer2,
					floatingPoint2,
					string2,
					pos);
	
	

	delete pack;
}

Output:

int: 32, float: 0.00, string: Hello., pos: 1
[SM] Plugin testcase.smx reloaded successfully.

@Headline
Copy link
Member

@Headline Headline commented Sep 20, 2017

So the test case for DataPack operations seems to work as expected now. Added errors for invalid type works great too.

👍 From me

Test case
public void OnPluginStart()
{
	int integer = 32;
	float floatingPoint = 32.0;
	char[] string = "Hello.";
	
	DataPack pack = new DataPack();
	
	pack.WriteCell(integer);
	pack.WriteFloat(floatingPoint);
	pack.WriteString(string);
		
	pack.Reset();
	
	int integer2;
	float floatingPoint2;
	char string2[8];
	
	integer2 = pack.ReadCell();
	floatingPoint2 = pack.ReadFloat();
	
	pack.ReadString(string2, sizeof(string2));
	
	PrintToServer("int: %i, float: %.2f, string: %s",
					integer2,
					floatingPoint2,
					string2);
	
	char string3[8];
	PrintToServer("%i", pack.Position);
	pack.Position--; // go back to string
	PrintToServer("%i", pack.Position);

	pack.ReadString(string3, sizeof(string3));
	PrintToServer("%s", string3);
	
	delete pack;
}
Actual output
int: 32, float: 32.00, string: Hello.
3
2
Hello.
[SM] Plugin testcase.smx reloaded successfully.

@KyleSanderson KyleSanderson requested a review from asherkin Sep 20, 2017
Copy link
Contributor

@Fyren Fyren left a comment

In theory, I think we want an IDataPack2. IsReadable's semantics basically assume the one contiguous block of memory model and this has pretty different performance characteristics.

In practice, do we care? Does any extension even use this?

typedef union {
cell_t cval;
float fval;
void *vval;
Copy link
Contributor

@Fyren Fyren Oct 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should definitely not be a void*, as mentioned in IRC. An AString* and a uint8_t* if raw is kept, otherwise just the AString*. This allows you to get rid of the casts.

{
return pContext->ThrowNativeError("DataPack operation is out of bounds.");
}

if (pDataPack->GetCurrentType() != CDataPackType::Cell)
{
return pContext->ThrowNativeError("Invalid Datapack Type (got %d / expected %d).", pDataPack->GetCurrentType(), CDataPackType::Cell);
Copy link
Contributor

@Fyren Fyren Oct 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check all the error messages for consistency, including the ones you didn't touch. The docs use "data pack" and errors shouldn't be in title case but normal sentence case.

I'd also recommend prettifying the enum types for the user so they see names and not the integer value of the enum. Lots (most? all?) of our other errors don't do anything like that, so it's definitely not required.

}

void CDataPack::ResetSize()
{
m_size = 0;
this->Initialize();
}

size_t CDataPack::CreateMemory(size_t size, void **addr)
Copy link
Contributor

@Fyren Fyren Oct 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we even know if a single person is using the generic/raw memory functions? This functionality is not exposed to plugins, so it'd have to be an extension. I'd be in favor of axing these completely. (Since they're in the interface, just make them no-ops/return null.)

If they're kept, the docs in IDataPack.h about pointers being invalidated (in the case of realloc) are wrong and should be updated.

You also alloc a byte more than necessary? Did you mean to store the size here (originally stored as 32-bits)? Related to the behavior change I mention for ReadMemory?


size_t real_len = *(size_t *)m_curptr;
if (!this->IsReadable())
return "";
Copy link
Contributor

@Fyren Fyren Oct 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API says "pointer to the string, or NULL if out of bounds," so the old behavior seems correct to me. We should actually use nullptr now, though (and switch any other uses in the file as well).

return NULL;
}
if (this->elements[this->position].type != CDataPackType::String)
return "";
Copy link
Contributor

@Fyren Fyren Oct 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API doesn't say what would happen in this case, but the old behavior was to return NULL, so I'd also make it nullptr.

if (this->elements[this->position].type != CDataPackType::Raw)
return nullptr;

return this->elements[this->position].pData.vval;
}

void *CDataPack::ReadMemory(size_t *size) const
Copy link
Contributor

@Fyren Fyren Oct 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Behavior here appears to have changed? The old behavior checked the stored size was <= the requested size and returned null if it wasn't. It also returned the real size of the memory chunk, which you haven't stored.

m_pBase = (char *)malloc(DATAPACK_INITIAL_SIZE);
m_capacity = DATAPACK_INITIAL_SIZE;
Initialize();
this->Initialize();
Copy link
Contributor

@Fyren Fyren Oct 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style: Why are you using this-> everywhere? SM code in general doesn't appear to use this style.

void CDataPack::CheckSize(size_t typesize)
{
if (m_curptr - m_pBase + typesize <= m_capacity)
for (size_t iter = 0; iter < this->elements.length(); ++iter)
Copy link
Contributor

@Fyren Fyren Oct 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style: this isn't an iterator, it's an index.

m_curptr += real_len + 1;

return str;
return val.chars();
}

void *CDataPack::GetMemory() const
Copy link
Contributor

@Fyren Fyren Oct 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not the same behavior. The analogue in the new implementation would be returning the address of the InternalPack. However, I don't see how/why anyone would ever use this function because the pointer is opaque to the user.

m_curptr += sizeof(float);
return val;

return this->elements[this->position++].pData.fval;
}

bool CDataPack::IsReadable(size_t bytes) const
Copy link
Contributor

@Fyren Fyren Oct 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs here utterly suck. The imply the old implementation and so this is not really satisfiable with the new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants