SA-MP Forums Archive
[Tutorial] Packed strings in PAWN - Printable Version

+- SA-MP Forums Archive (https://sampforum.blast.hk)
+-- Forum: SA-MP Scripting and Plugins (https://sampforum.blast.hk/forumdisplay.php?fid=8)
+--- Forum: Scripting Help (https://sampforum.blast.hk/forumdisplay.php?fid=12)
+---- Forum: Tutorials (https://sampforum.blast.hk/forumdisplay.php?fid=70)
+---- Thread: [Tutorial] Packed strings in PAWN (/showthread.php?tid=480529)



Packed strings in PAWN - Emmet_ - 11.12.2013

Packed strings in PAWN

Introduction
Packed strings have been a feature in SA-MP and PAWN since the beginning. However, many people are unaware of packed strings and the memory reduction! This tutorial will teach you the basics of packed strings, and how to manipulate them accordingly.

What is a packed string?
A packed string is an array that stores data in each byte, rather than each cell, opposed to regular arrays. Packed strings are stored in Little Endian (meaning, lower byte first) and can only hold ASCII characters from 0 to 255, and anything exceeding those numbers will just wrap around.

Picture this code:

pawn Код:
new string[5];

string[0] = 'a';
string[1] = 'b';
string[2] = 'c';
string[3] = 'd';
string[4] = '\0';
'a' is stored in cell 0, 'b' is stored in cell 1, and so on. A cell is basically 4 bytes, so if we do the math, that string above is approximately 20 bytes in size, so each character is stored in a 4 byte set.

However, with this code:

pawn Код:
new string[5 char];

string{0} = 'a';
string{1} = 'b';
string{2} = 'c';
string{3} = 'd';
string{4} = '\0';
'a' is stored in byte 0, 'b' is stored in byte 1, and so on. Basically, that string above is only 8 bytes in size and contains only 2 cells!

You're probably wondering why that string isn't 5 bytes. Using "char" automatically rounds the number to the next nearest multiple of 4 (for example, 1 turns into 4, 3 turns into 4, 5 turns into 8, 23 turns into 24, and so on).

pawn Код:
// This array is 5 cells big and 20 bytes in size.
new string[5] = "abcd";

// This array is 2 cells big and 8 bytes in size.
new string[5 char] = !"abcd"
So you're saving 3-4 times the memory with packed strings!

Areas of use
You might think that packed arrays are useless. If so, then you're wrong. There are many uses for packed arrays, and not just for memory reduction!
Unsupported in SA-MP
Packed strings are fluently supported in pure PAWN. However, most of the SA-MP natives do NOT support packed strings, such as format, GetPlayerName, etc.

If you plan on using packed strings, you have to rely on "strpack" and "strunpack" and the other string functions, which you can find in string.inc.
Accessing the data
Unpacked arrays in PAWN store data in each cell. Packed arrays in PAWN store data in each byte, which means that you can't use square brackets, like you do with unpacked arrays, to access and obtain data inside packed arrays.

pawn Код:
// Incorrect.
if (g_PackedString[0] != '\0')
{
    g_PackedString[0] = 'h';
    g_PackedString[1] = 'i';
}

// Correct!
if (g_PackedString{0} != '\0')
{
    g_PackedString{0} = 'h';
    g_PackedString{1} = 'i';
}
Also, to set a packed string, you have to place an exclamation mark before the string, to denote that it's a packed input.

pawn Код:
// Incorrect. This will try and store the string in each cell, which is not what we want!
g_PackedString = "Hello world.";

// Correct!
g_PackedString = !"Hello world.";
Conclusion
There is more information on packed strings in the PAWN language guide - you can get it here:

https://sampforum.blast.hk/showthread.php?tid=289258

You can also read the "String Manipulation" guide, which covers most information about packed strings:

http://www.compuphase.com/pawn/String_Manipulation.pdf

Anyways, I hope you learned something new today (and if you didn't, go sit in the corner and think about what you've done). Thanks for reading!


Re: Packed strings in PAWN - Hansrutger - 11.12.2013

Nice way to save some space, will come back into the future when I will need to save more memory. :P


Edit: Hello future me!


Re: Packed strings in PAWN - Emmet_ - 11.12.2013

Quote:
Originally Posted by ******
Посмотреть сообщение
4 * 4 = 12

Err...
Woops, hahahaha, let me change that :D.


Re: Packed strings in PAWN - Emmet_ - 11.12.2013

Quote:
Originally Posted by ******
Посмотреть сообщение
I edited my last post, but I should say it is good to see more on these - I know I don't use them as often as I probably should. Slice advocates them a lot though and its good to see others doing the same.
Yeah, thanks for clearing that up! I edited the post with the new information.

I agree, it's nice to see others utilizing packed strings as well, but there are others that don't and should use it where appropriate, like for example they still use the standardized 2 dimension arrays for mass data storage.


Re: Packed strings in PAWN - Emmet_ - 11.12.2013

Thanks, just fixed that. I keep forgetting that using "char" with any number that's not a multiple of 4 will simply round up to the nearest multiple of 4! I should probably note that in the first post.


AW: Packed strings in PAWN - BigETI - 12.12.2013

It does not only benefit for strings, it also benefits plain data aswell. It allows you to have easier bytewise access to a larger memory field.

pawn Код:
new something[1];
//...
something{0} = varchar_1;
//...
something{1} = varchar_2;
//...
something{2} = varchar_3;
//...
something{3} = varchar_4
instead of
pawn Код:
new something;
//...
something = (something&0xFFFFFF00)|varchar_1;
//...
something = (something&0xFFFF00FF)|(varchar_2<<8);
//...
something = (something&0xFF00FFFF)|(varchar_3<<16);
//...
something = (something&0xFFFFFF)|(varchar_4<<24);



Re: Packed strings in PAWN - Emmet_ - 12.12.2013

Yeah, thanks for the reminder! Although this is merely a tutorial on strings, I'll add it for the sake of completing the tutorial (after all, it's still in the same category).

I just noticed that rBits and y_bit use cell shifting and packed arrays too. Awesome!


Respuesta: Packed strings in PAWN - Swedky - 17.12.2013

Oh Emmet _, thank you very much.

I did not like to translate from English the Spanish, and to translate other things since this translator is a garbage, but it was worth a sorrow reading everything.

You gave to me a great push to optimize my GM, thousands of graces my shaggy friend .



Re: Packed strings in PAWN - Konstantinos - 24.12.2013

I do use packed strings and I had to reset the string for something I was making. I tried to use EOS ('\0') but it seems that it doesn't make the packed string NULL.

I run this code (here: http://slice-vps.nl:7070/#):
pawn Код:
#include <a_samp>

#if !defined isnull
    #define isnull(%1) \
        ((!(%1[0])) || (((%1[0]) == '\1') && (!(%1[1]))))
#endif

static stock
    Player_Name[MAX_PLAYERS][MAX_PLAYER_NAME char];
   
main()
{
    strpack(Player_Name[0], "Konstantinos", MAX_PLAYER_NAME);
    SetTimer("PrintName", 1000, false);
}

forward PrintName();
public PrintName()
{
    new
        sz_T[MAX_PLAYER_NAME];
   
    strunpack(sz_T, Player_Name[0], MAX_PLAYER_NAME);
    printf("Player_Name: \"%s\" -> %s", sz_T, (isnull(sz_T)) ? ("NULL") : ("NOT NULL"));
    Player_Name[0]{0} = EOS;
    SetTimer("PrintName2", 1000, false);
}

forward PrintName2();
public PrintName2()
{
    new
        sz_T[MAX_PLAYER_NAME];
   
    strunpack(sz_T, Player_Name[0], MAX_PLAYER_NAME);
    printf("Player_Name: \"%s\" -> %s", sz_T, (isnull(sz_T)) ? ("NULL") : ("NOT NULL"));
}
The output was:
pawn Код:
Player_Name: "Konstantinos" -> NOT NULL
Player_Name: "sts" -> NOT NULL
I then used:
pawn Код:
#include <a_samp>

#if !defined isnull
    #define isnull(%1) \
        ((!(%1[0])) || (((%1[0]) == '\1') && (!(%1[1]))))
#endif

static stock
    Player_Name[MAX_PLAYERS][MAX_PLAYER_NAME char];
   
main()
{
    strpack(Player_Name[0], "Konstantinos", MAX_PLAYER_NAME);
    SetTimer("PrintName", 1000, false);
}

forward PrintName();
public PrintName()
{
    new
        sz_T[MAX_PLAYER_NAME];
   
    strunpack(sz_T, Player_Name[0], MAX_PLAYER_NAME);
    printf("Player_Name: \"%s\" -> %s", sz_T, (isnull(sz_T)) ? ("NULL") : ("NOT NULL"));
    strpack(Player_Name[0], "\0", MAX_PLAYER_NAME);
    SetTimer("PrintName2", 1000, false);
}

forward PrintName2();
public PrintName2()
{
    new
        sz_T[MAX_PLAYER_NAME];
   
    strunpack(sz_T, Player_Name[0], MAX_PLAYER_NAME);
    printf("Player_Name: \"%s\" -> %s", sz_T, (isnull(sz_T)) ? ("NULL") : ("NOT NULL"));
}
And the output was:
pawn Код:
Player_Name: "Konstantinos" -> NOT NULL
Player_Name: "" -> NULL
It is NULL like I wanted to but is it the correct way of resseting a packed string?


Re: Packed strings in PAWN - newbienoob - 24.12.2013

So... I can do something like this?
pawn Код:
new var[MAX_PLAYERS char];
//---
var{playerid} = 0;
//or
if(var{playerid} == 0)