[Plugin] RL_FILES - makes your life easy
#1

RL_FILES - makes your life easy
version: 1.3.1, tutorial: here

Hello,
Know the feeling when you must create loop over whole directory?
And what if the file names not "1.ini, 2.ini 3.ini"? Yes, This plugin will fix this!

Some time ago i asked how to do this (here) and get this answer:
Quote:

This is just in case you saved the files in numerical order.

And now I have developed little plugin that will fix this.

Installation
Simply, In "server.cfg" add:
Код:
plugins X rl_files.dll X
And where you want to use the plugin add at the top:
pawn Код:
#include <rl_files>
Functions - Files
fcheck - check if file exist by id,
pawn Код:
fcheck(dir[], idx)
dir - The directory where you check if file exist in
idx - id of the file that you checking
pawn Код:
if(!fcheck(NULL_DIR, 0)) return 1;
fnum - count number of files in directory,
pawn Код:
fnum(dir[])
dir - The directory where you count the files
pawn Код:
new
    test = fnum(NULL_DIR);
fname - returns file name by id,
pawn Код:
fname(dir[], idx, name[], len = sizeof(name))
dir - The directory where your files in
idx - id of the file that you want to get
name - variable that stores the name of the file
len(optional) - maximum length of the name
pawn Код:
new
    file[32];
fname(NULL_DIR, 0, file);
printf("%s", file);
fprint - print all files in directory,
pawn Код:
fprint(dir[])
dir - The directory where you want to print all files
pawn Код:
fprint(NULL_DIR);
fend - delete the file ext,
pawn Код:
fend(file[])
file - file name with ext
pawn Код:
printf("file name \"test.ini\" without ext is: \"%s\"", fend("test.ini"));
Functions - Directories
dopen - Open specific directory,
pawn Код:
Dir:dopen(const dir[])
dir[] - The directory that you want to open
pawn Код:
new
        Dir:test = dopen("test");
dreopen - reOpen already opened directory,
pawn Код:
dreopen(Dir:dir)
Dir:dir - The opened directory that you want to re-open
pawn Код:
dreopen(test);
dread - Read files / directories from already opened dir,
pawn Код:
dread(Dir:dir, file[], &type)
Dir:dir - The opened directory that you want to read from
pawn Код:
while(dread(test, str, type)) {
    printf("%s: %s, type: %d", (type == TYPE_DIR)? ("dir"):("file"), str, type);
}
dclose - Close (end) working with directory,
pawn Код:
dclose(Dir:dir)
Dir:dir - The opened directory that you want to close
pawn Код:
dclose(test);
dcreate - Create directory,
pawn Код:
dcreate(const dir[])
dir[] - Name of the directory that you want to create
pawn Код:
dcreate("test");
dremove - Delete directory,
pawn Код:
dremove(const dir[], bool:empty = true)
dir[] - Name of the directory that you want to
pawn Код:
dremove("test", true);
drename - Rename directory,
pawn Код:
drename(const oldname[], const newname[])
dir[] - Name of the directory that you want to
pawn Код:
drename("test", "test2");
dexist - Check if specific directory exist,
pawn Код:
dexist(const dir[])
dir[] - Name of the directory that you want to
pawn Код:
if(dexist("test"))
        print("folder \"test\" exists!");
Examples
Here is my files:
Код:
Ccsds.tdssa
hdgsadgsa.dshdg
dsjhfkfdg.dssdsaf
hmmippewg.dsa
test.iinfhfbd
We can do loop over all files in the directory
pawn Код:
new
    idx,
    file[MAX_FILE_NAME];
while(idx < fnum(NULL_DIR)) {
    fname(NULL_DIR, idx, file);
    printf("file number %d: %s", idx, file);
    idx++;
}
This will print the flowing,
Quote:

file number 0: Ccsds.tdssa
file number 1: hdgsadgsa.dshdg
file number 2: dsjhfkfdg.dssdsaf
file number 3: hmmippewg.dsa
file number 4: test.iinfhfbd

Here some example how to create /ClanList command:
pawn Код:
if(!strcmp(cmdtext,"/ClanList",true)) {
    new
        idx,
        file[MAX_FILE_NAME];
    while(idx < fnum("Clans")) {
        fname("Clans", idx, file);
        SendClientMessage(playerid, 0xFF0000FF, fend(file)); // Send the message to client
        idx++;
    }
    return 1;
}
Here example of reading directory:
pawn Код:
// Reading Directories functions
    new
        Dir:test = dopen("test"), // Open directory
        str[64],
        type;

    while(dread(test, str, type)) { // Read directory
        printf("%s: %s, type: %d", (type == TYPE_DIR)? ("dir"):("file"), str, type);
    }

    dclose(test); // Close directory
Credits
Quote:

Thanks to:
RaFaeL - Scripting, PAWN
Kyosaur - How to build plugin
Gamer_Z - Help in passing arrays by reference
SA:MP Team past, present, future - SA:MP.

Quote:

By downloading this file you accept that you never will post it as yours!

Download
1.3.1:
Mediafire: http://www.mediafire.com/download.php?dsypn2vfbxam0l7
PasteBin (Include): http://pastebin.com/P2jAHzPc
Source: http://www.mediafire.com/download.php?phz1x848421xo40

1.2.7:
Mediafire: http://www.mediafire.com/?sv34wfoeee5b9e2
PasteBin (Include): http://pastebin.com/GyEgzfkK
Source: http://www.mediafire.com/?713o1ddl9aj2tym

1.2.4:
Mediafire: http://www.mediafire.com/?r8t9tl55rmv5fbz
PasteBin (Include): http://pastebin.com/6Gnk2Tw0
Source: http://www.mediafire.com/?713o1ddl9aj2tym

1.2.1:
Mediafire - http://www.mediafire.com/?1az34pcg20krlla
PasteBin (Include) - http://pastebin.com/YM68UVKb
Source - http://www.mediafire.com/?3kk28924r5txydi

Notes
Quote:

* There are no limit number of files in directory
* Soon I will release new version with allot of new function!
* There are limit to opened directories (16)

Bugs & Suggestions
Quote:

Known bugs:
* Some times there are "Empty lines" appers - Seems Done
Quote:

Suggestions (v1.3.1):
* In fend check if ext is there - Done
* farray, will make arrays of files, will improve the plugin performance asswell. - Freezed
* dmove, will give option to move directories with the files in it. - In progress
Whats new?
Quote:

v1.3.1:
* Dir:dopen(const dir[]) - Open directory
* dreopen(Dir:dir) - Reopen the directory (start file counting from 0)
* dread(Dir:dir, file[], &type) - Get files and sub directories from directory
* dclose(Dir:dir) - Close directory
* dcreate(const dir[]) - Create new directory
* dremove(const dir[], bool:empty = true) - Delete exist directory
* drename(const oldname[], const newname[]) - Rename directory to new name
* dexist(const dir[]) - Check if directory exist

Quote:

v1.2.7:
* Fixed bug in the plugin
* Default dir[] = "."

Quote:

v1.2.4:
* fnum(dir[]) now PAWN scripted function
* plugin speed performance is now fester

Enjoy!
Reply
#2

Very Purr-tas-tic!!!

Very useful!
Reply
#3

Useful for dynamic maps or any other files where you want to know the count.
Well done.
Reply
#4

nice n' nice
Reply
#5

Cool!
Reply
#6

There are better ways to do that but nevertheless good job.
Reply
#7

Nice !!!
Reply
#8

Very, very nice! I was also looking for this earlier, thank you! Rep+
Reply
#9

Thanks,
Tiday I will improve the performance and the plugin will faster...

Worth to wait!
Reply
#10

So basically, the only thing this plugin does is list all files in a directory?

Yay, a plugin that has less functionality than those that already exist.

https://sampforum.blast.hk/showthread.php?tid=92246 FileManager
https://sampforum.blast.hk/showthread.php?tid=177028 y_files
Reply
#11

Quote:
Originally Posted by ikkentim
View Post
So basically, the only thing this plugin does is list all files in a directory?

Yay, a plugin that has less functionality than those that already exist.

https://sampforum.blast.hk/showthread.php?tid=92246 FileManager
https://sampforum.blast.hk/showthread.php?tid=177028 y_files
I don't see where those plugins gives you option to get file name by id in directory.

Updated!
new version 1.2.4 now available!
Reply
#12

Nice plugin, I'm wondering if it's possible to fill multidimenstional arrays from a plugin into pawn, if yes I think it would be faster to make a function which lists all files into a multidimenstional array like "new FileNamesInDir[][267];", ofcourse this would need alot of memory usage for the script, (well we're talking about a few megabytes here, not hundreds of megabytes or gigabytes) but the performance gain would be cool because then you would only need to call one function to loop 200 files instead of 200 times a function.
Reply
#13

Quote:
Originally Posted by Gamer_Z
View Post
Nice plugin, I'm wondering if it's possible to fill multidimenstional arrays from a plugin into pawn, if yes I think it would be faster to make a function which lists all files into a multidimenstional array like "new FileNamesInDir[][267];", ofcourse this would need alot of memory usage for the script, (well we're talking about a few megabytes here, not hundreds of megabytes or gigabytes) but the performance gain would be cool because then you would only need to call one function to loop 200 files instead of 200 times a function.
I tried to do this but is no way to set array in AMX SDK...
Reply
#14

Quote:
Originally Posted by Swimor
View Post
I tried to do this but is no way to set array in AMX SDK...
There is a way to set arrays, but I don't know how about multidimensional arrays.

pawn Code:
/This function demonstrates: how to get and modify array values.
//PAWN native: native PrintPawnArray(arr[], size = sizeof(arr));
cell AMX_NATIVE_CALL PrintPawnArray(AMX* amx, cell* params)
{
    //Make sure there's something to print...
    if(params[2] > 0)
    {
        cell* addr = NULL;

        //Get the address of the first value in our PAWN array.
        amx_GetAddr(amx, params[1], &addr);

        for(int i = 0, l = params[2]; i < l; i++)
        {
            //This is pretty straight forward: We dereference the addr pointer to get our value to print.
            //You should know this already, but arrays and pointers are almost the same thing, so we can use pointer
            //arithmetic to add an offset OR just use the subscript operator (in the end *(addr+1) and addr[1] are the same).
            logprintf("arr[%d] = %d", i, *(addr + i));

            //If you wanted to modify the array you would just change its value by dereferencing addr and assigning a new value.
            //You should know this as well, im just adding it in for completeness. Here we change the first value of our array
            //to 5 (Note: Since its the first value, no offset it used).

            // *(addr) = 5;  
        }
    }
    return 1;
}
from plugin development topic
Reply
#15

Quote:
Originally Posted by Gamer_Z
View Post
There is a way to set arrays, but I don't know how about multidimensional arrays.

pawn Code:
/This function demonstrates: how to get and modify array values.
//PAWN native: native PrintPawnArray(arr[], size = sizeof(arr));
cell AMX_NATIVE_CALL PrintPawnArray(AMX* amx, cell* params)
{
    //Make sure there's something to print...
    if(params[2] > 0)
    {
        cell* addr = NULL;

        //Get the address of the first value in our PAWN array.
        amx_GetAddr(amx, params[1], &addr);

        for(int i = 0, l = params[2]; i < l; i++)
        {
            //This is pretty straight forward: We dereference the addr pointer to get our value to print.
            //You should know this already, but arrays and pointers are almost the same thing, so we can use pointer
            //arithmetic to add an offset OR just use the subscript operator (in the end *(addr+1) and addr[1] are the same).
            logprintf("arr[%d] = %d", i, *(addr + i));

            //If you wanted to modify the array you would just change its value by dereferencing addr and assigning a new value.
            //You should know this as well, im just adding it in for completeness. Here we change the first value of our array
            //to 5 (Note: Since its the first value, no offset it used).

            // *(addr) = 5;  
        }
    }
    return 1;
}
from plugin development topic
This is not set, here he prints all array content.
If your array is:

new array[] = { 1, 2, 3, 4, 5, 6, 7};

This will print:
arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[3] = 4
arr[4] = 5
arr[5] = 6
arr[6] = 7
Reply
#16

Quote:
Originally Posted by Swimor
View Post
This is not set, here he prints all array content.
If your array is:

new array[] = { 1, 2, 3, 4, 5, 6, 7};

This will print:
arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[3] = 4
arr[4] = 5
arr[5] = 6
arr[6] = 7
Then look into my route connector plugin source on how to set single dimension array : )

pawn Code:
static cell AMX_NATIVE_CALL n_ReturnArray( AMX* amx, cell* params )
    {
        for(int i = 0, j = RouteVector.size(); i < j; ++i)
        {
            if(RouteVector.at(i).id == params[1])
            {
                cell *dest = NULL;
                amx_GetAddr(amx,params[2],&dest);
                for(int a = 0, b = params[3]; a < b; ++a)
                {
                    dest[a] = RouteVector.at(i).Paths[a];
                }
                //dest = NULL;
                return RouteVector.at(i).Paths.size();
            }
        }
        return 0;
    }
:P
Reply
#17

Awesome plugin. Now i can simply load maps and vehicles
Reply
#18

Nice Plugin.
Will help the people who don't want to convert their gamemode from y_ini to mysql
Reply
#19

Quote:
Originally Posted by QuaTTrO
View Post
Awesome plugin. Now i can simply load maps and vehicles
Tahkns.

Quote:
Originally Posted by [HK]Ryder[AN]
View Post
Nice Plugin.
Will help the people who don't want to convert their gamemode from y_ini to mysql
Thanks!

Updated!
New version 1.2.7 is now available with bug fixes!
Reply
#20

1) Please delete .SDF files from source code and .PCH files and (ipc,Debug,Release) directories, this will make redistribution smaller and faster.

2) This:

Here, I made some code for you while playing around in my plugin:
pawn Code:
namespace Natives
{
    //native TwoDArrayFunction(array[][],size_a = sizeof(array),size_b = sizeof(array[]));
    static cell AMX_NATIVE_CALL TwoDArrayFunction( AMX* amx, cell* params )
    {
        cell *dest = NULL;
        amx_GetAddr(amx,params[1],&dest);

        for(int a = params[2], b = a+(params[2]*params[3]); a < b; ++a)
        {
            std::cout << dest[a] << std::endl;
        }
        return 1;
    }
    //native ThreeDArrayFunction(array[][][],size_a = sizeof(array),size_b = sizeof(array[]),size_c = sizeof(array[][]));
    static cell AMX_NATIVE_CALL ThreeDArrayFunction( AMX* amx, cell* params )
    {
        cell *dest = NULL;
        amx_GetAddr(amx,params[1],&dest);

        for(int a = (params[2]*params[3])+params[2], b = a+(params[2]*params[3]*params[4]); a < b; ++a)
        {
            std::cout << dest[a] << std::endl;
            //dest[a] = 0;//modify array
        }
        return 1;
    }
    //native SomeStringfunc(array[][],size_a = sizeof(array),size_b = sizeof(array[]));
    static cell AMX_NATIVE_CALL SomeStringfunc( AMX* amx, cell* params )
    {
        cell *dest = NULL;
        amx_GetAddr(amx,params[1],&dest);

        for(int a = params[2], b = a+(params[2]*params[3]); a < b; a+=params[3])
        {
            //std::cout << dest[a] << std::endl;
            amx_SetString(&dest[a],"This is a test string\0",0,0,strlen("This is a test string\0")+1);
        }
        return 1;
    }
    AMX_NATIVE_INFO AMXNatives[ ] =
    {
        {"TwoDArrayFunction", TwoDArrayFunction},
        {"ThreeDArrayFunction", ThreeDArrayFunction},
        {"SomeStringfunc", SomeStringfunc},
        {0,                0}
    };
};//namespace Natives
usage:

pawn Code:
#include <a_samp>

native TwoDArrayFunction(array[][],size_a = sizeof(array),size_b = sizeof(array[]));
native ThreeDArrayFunction(array[][][],size_a = sizeof(array),size_b = sizeof(array[]),size_c = sizeof(array[][]));
native SomeStringfunc(array[][],size_a = sizeof(array),size_b = sizeof(array[]));
/*
enum ArrayStuff7
{
    SomeStuff7[7]
};

enum ArrayStuff5
{
    SomeStuff5[5]
};
*/

public OnFilterScriptInit()
{
    new array1[3][5];
    //new array2[3][ArrayStuff5];
    new array3[3][5][7];
    //new array4[3][5][ArrayStuff7];
    for(new a = 0,b,c,z=0,y=0; a < 3; ++a)
    {
        for(b = 0; b < 5; ++b)
        {
            array1[a][b] = z;
            //array2[a][SomeStuff5][b] = z;
            ++z;
            //printf("2)[%d][%d] = (%d)",a,b,array2[a][b]);
            for(c = 0; c < 7; ++c)
            {
                array3[a][b][c] = y;
                //array4[a][b][SomeStuff7][c] = y;
                //printf("3)[%d][%d] = (%d)",a,b,array3[a][b][c]);
                ++y;
            }
        }
    }
    printf("done");
    TwoDArrayFunction(array1);
    //TwoDArrayFunction(array2);
    ThreeDArrayFunction(array3);
    //ThreeDArrayFunction(array4);
    new strings[10][256];
    SomeStringfunc(strings);
    for(new i = 0; i < 10; ++i)
        print(strings[i]);
    return 1;
}


as for the "int a = (params[2]*params[3])+params[2])" , I don't understand why amx_GetAddr isn't pointing to the array start but some weird values, maybe array information? Dunno, but this is the right way to loop all possible multidimensional arrays. array[][][][] is not possible so don't worry.

Now you can make a function like PutAllDirectoryFilesInArray(directory[],contents[][]); and PutAllDirectoryDirectoriesInArray(directory[],contents[][]);

3)if you really want to make these functions, here is a detailed design/code info:

Each array has a limited size, so, if there are 50,000 files in a directory and the array size is only able to hold 100 strings, then we only assign the first 100 files, but suppose we want to assign file indexes 100 to 200, then we need to know an index, so our function definition will look like:

native RetrieveFileList(directory[],array[][],&returned_files=0,&index=0,size_a = sizeof(array),size_b = sizeof(array[]));

Our function in the plugin would look like this then (pseudocode):

pawn Code:
//native RetrieveFileList(directory[],array[][],&returned_files=0,&index=0,size_a = sizeof(array),size_b = sizeof(array[]));
    static cell AMX_NATIVE_CALL TwoDArrayFunction( AMX* amx, cell* params )
    {
        char* DirectoryToLoop;

        cell * index = NULL;
        amx_GetAddr(amx,params[4],&index);
        cell *returned_files = NULL;
        amx_GetAddr(amx,params[3],&returned_files);

        returned_files = 0;

        amx_StrParam(amx, params[1], DirectoryToLoop);
        if(!DirectoryToLoop)
            DirectoryToLoop = ".";
        if(index < 0)
            return false;

        cell *dest = NULL;
        amx_GetAddr(amx,params[1],&dest);

        int ArrayIdxStart = params[5];
        int ArrayStep = params[6];
        int ArrayMax = ArrayIdxStart+(ArrayIdxStart*ArrayStep);
       
        int LoopsDone = 0;

        int WriterPosition = 0;
        foreach(|file| in {DirectoryToLoop}, start looping files at {index})
        {
            WriterPosition = ArrayIdxStart+(ArrayStep*LoopsDone);
            if(WriterPosition < ArrayMax)
            {
                amx_SetString(&dest[ArrayIdxStart+(ArrayStep*LoopsDone)],file,0,0,strlen(file)+1);
            }
            else
            {
                index = index+(LoopsDone);
                returned_files = (LoopsDone+1);
                return (|files in directory| - index);//we still have files to loop
            }
            ++LoopsDone;
        }
        index = index+(LoopsDone-1);
        returned_files = (LoopsDone);
        return 0;//no more files to loop
    }
Usage:

pawn Code:
#include <a_samp>
native RetrieveFileList(directory[],array[][],&returned_files=0,&index=0,size_a = sizeof(array),size_b = sizeof(array[]));

new MyArrayOfFiles[32][267];

public OnFilterScriptInit()
{
    //print all files in directory "./scriptfiles/"
    new index = 0;
    new FilesReturned = 0;
    while(RetrieveFileList("./scriptfiles/",MyArrayOfFiles,FilesReturned,index))
    {
        for(new i = 0; i < FilesReturned; ++i)
        {
            print(MyArrayOfFiles[i]);
        }
    }
    return 1;
}
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)