alliedmodders / sourcemod Public
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
Conversation
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:
|
Tested-By: Headline22.
So the test case for DataPack operations seems to work as expected now. Added errors for invalid type works great too. Test casepublic 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
|
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?
core/logic/CDataPack.h
Outdated
typedef union { | ||
cell_t cval; | ||
float fval; | ||
void *vval; |
There was a problem hiding this comment.
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.
core/logic/smn_datapacks.cpp
Outdated
{ | ||
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); |
There was a problem hiding this comment.
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.
core/logic/CDataPack.cpp
Outdated
} | ||
|
||
void CDataPack::ResetSize() | ||
{ | ||
m_size = 0; | ||
this->Initialize(); | ||
} | ||
|
||
size_t CDataPack::CreateMemory(size_t size, void **addr) |
There was a problem hiding this comment.
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?
core/logic/CDataPack.cpp
Outdated
|
||
size_t real_len = *(size_t *)m_curptr; | ||
if (!this->IsReadable()) | ||
return ""; |
There was a problem hiding this comment.
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).
core/logic/CDataPack.cpp
Outdated
return NULL; | ||
} | ||
if (this->elements[this->position].type != CDataPackType::String) | ||
return ""; |
There was a problem hiding this comment.
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
.
core/logic/CDataPack.cpp
Outdated
if (this->elements[this->position].type != CDataPackType::Raw) | ||
return nullptr; | ||
|
||
return this->elements[this->position].pData.vval; | ||
} | ||
|
||
void *CDataPack::ReadMemory(size_t *size) const |
There was a problem hiding this comment.
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.
core/logic/CDataPack.cpp
Outdated
m_pBase = (char *)malloc(DATAPACK_INITIAL_SIZE); | ||
m_capacity = DATAPACK_INITIAL_SIZE; | ||
Initialize(); | ||
this->Initialize(); |
There was a problem hiding this comment.
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.
core/logic/CDataPack.cpp
Outdated
void CDataPack::CheckSize(size_t typesize) | ||
{ | ||
if (m_curptr - m_pBase + typesize <= m_capacity) | ||
for (size_t iter = 0; iter < this->elements.length(); ++iter) |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
core/logic/CDataPack.cpp
Outdated
m_curptr += sizeof(float); | ||
return val; | ||
|
||
return this->elements[this->position++].pData.fval; | ||
} | ||
|
||
bool CDataPack::IsReadable(size_t bytes) const |
There was a problem hiding this comment.
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.
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.