Buffer/stack with Arrays (limiting array size) UDF

1 post in this topic

#1 ·  Posted (edited)

At my work I was creating a music player (truly the project is bigger than it but it doesn't come to the case right now) and, given some conditions, it should start playing songs randomly. I've used Random() function to sort any song from the list, but the "random wasn't so random" sometimes, and some songs used to repeat multiple times, although the song list wasn't so small. So I needed to keep a list of all the played songs. However, I couldn't feed up an array forever as this system I'm working on is meant to work 24/7 with no pause and the array could really reach huge values, while just the latest X values would really be used (to check if a random song was played recently before playing it).

So I managed to create this simple stack/buffer/heap script. It works just like Assembly stacks (although the target is totally different). You'll have an array, you can define its max size and start adding items into it. Once the array limit is reached, the first added item is automatically removed, all the other items are reindexed and your new item will then be added.

You can also change the array (stack) limit at any time, reset it as well as pull/remove or read the last added item. In the best Assembly stack way, you shouldn't be able to read all the items, except the last added item. But, well, we are talking about AutoIt arrays. It's just a list, where the 0 index brings the actual items count. This means you can easily create loops and read the array as you want (just be very careful if you want to modify the array without _Buffer* functions).

It's also useful if you want to generate random values with Random() with repeating values, but they're repeating more than you want (instead of "1-2-2-2-3-1-2-3-4" you would have "1-3-2-4-3-1-2-4" - the values would only start repeating after it's too long since they were generated in last).

Here's an example:

#inclcude 'buffer.au3' ; the lib
#include <Array.au3> ; needed only to do _ArrayDisplay

; Example 1
$aBuffer = _BufferCreate(3)
_BufferPush($aBuffer, 12)
_BufferPush($aBuffer, 23)
_BufferPush($aBuffer, 34)
_BufferPush($aBuffer, 45)
MsgBox(0, '', _BufferPull($aBuffer)) ; 45 (and remove it)
_BufferPush($aBuffer, 56)
_BufferPush($aBuffer, 67)

; Example 2
$aBuffer = _BufferCreate(3)
_BufferPush($aBuffer, 12)
_BufferPush($aBuffer, 23)
_BufferPush($aBuffer, 34)
_BufferPush($aBuffer, 45)
_BufferChangeLimit($aBuffer, 6)
_BufferPush($aBuffer, 56)
_BufferPush($aBuffer, 67)
MsgBox(0, "", "Buffer items count: " & _BufferItemsCount($aBuffer) & @CRLF & "Buffer max size: " & _BufferLimit($aBuffer) & @CRLF & "Last item (without pulling/removing it): " & _BufferGetLastItem($aBuffer))

; Example 3
$aBuffer = _BufferCreate(3)
_BufferPush($aBuffer, 'ab')
_BufferPush($aBuffer, 'cd')
_BufferPush($aBuffer, 'ef')
_BufferPush($aBuffer, 'gh')

; Example 4
$aBuffer = _BufferCreate(2)
_BufferPush($aBuffer, 'Song 1')
_BufferPush($aBuffer, 'Music 2')
_BufferPush($aBuffer, 'Hit 3')
If _BufferCheckValue($aBuffer, 'Song 1') Then ; False
   MsgBox(0, "", "Song 1 was played too recently.")
If _BufferCheckValue($aBuffer, 'Music 2') Then ; True
   MsgBox(0, "", "Music 2 was played too recently.")

The lib source code:


   Buffer/stack/heap UDF
   made by Jefrey <jefrey[at]>
   Licensed under WTFPL:

; Creates a new buffer
; Arguments: $iSize - size of the buffer (limit)
Func _BufferCreate($iSize)
   Local $aBuffer[$iSize+1]
   $aBuffer[0] = 0
   Return $aBuffer

; Adds an item to the buffer
; If the buffer limit was reached, then the first item will be removed.
; Arguments: $aBuffer - buffer to change (reference) / $mItem - item to add
Func _BufferPush(ByRef $aBuffer, $mItem)
   If $aBuffer[0]+1 > UBound($aBuffer)-1 Then
      ; remove first item and reindex
      $aBuffer[1] = Null
      For $i = 2 To $aBuffer[0]
         $aBuffer[$i - 1] = $aBuffer[$i]
      $aBuffer[0] += 1
   $aBuffer[$aBuffer[0]] = $mItem
   Return $aBuffer

; Removes the last added item of the buffer and returns its value
; Arguments: $aBuffer - buffer to change (reference)
Func _BufferPull(ByRef $aBuffer)
   If $aBuffer[0] = 0 Then Return
   $mReturn = $aBuffer[$aBuffer[0]]
   $aBuffer[$aBuffer[0]] = Null
   $aBuffer[0] -= 1
   Return $mReturn

; Returns the actual items count (how many items were added to the buffer, and not its limit)
; Arguments: $aBuffer - the buffer
Func _BufferItemsCount($aBuffer)
   Return $aBuffer[0]

; Returns the actual items count (how many items were added to the buffer, and not its limit)
; Arguments: $aBuffer - the buffer
Func _BufferGetLastItem($aBuffer)
   Return $aBuffer[$aBuffer[0]]

; Returns the buffer limits (that were set by you)
; Arguments: $aBuffer - the buffer
Func _BufferLimit($aBuffer)
   Return UBound($aBuffer)-1

; Changes a buffer limit
; Arguments: $aBuffer - the buffer to change / $iSize - new buffer size
Func _BufferChangeLimit(ByRef $aBuffer, $iSize)
   ReDim $aBuffer[$iSize + 1]
   Return $aBuffer

; Resets a buffer (removes all items)
; Arguments: $aBuffer - the buffer to change
Func _BufferReset(ByRef $aBuffer)
   Local $j = UBound($aBuffer)-1
   For $i = 1 To $j
      $aBuffer[$i] = Null
   $aBuffer[0] = 0

; Checks if a value exists in a buffer
; Returns: 0 if not found or index (>0) of where it was found
Func _BufferCheckValue($aBuffer, $mValue)
   If Not $aBuffer[0] Then Return 0
   For $i = 1 To $aBuffer[0]
      If $aBuffer[$i] = $mValue Then Return $i
   Return 0


Edited by Jefrey
_BufferCheckValue added

My UDFs  _AuThread multithreading emulation for AutoIt · _ExtInputBox an inputbox with multiple inputs and more features · forceUTF8 fix strings encoding without knowing its original charset · JSONgen JSON generator · _TCPServer UDF multi-client and multi-task (run on background) event-based TCP server easy to do · _TCPClient_UDF multi-server and multi-task (runs on background) event-based TCP client easy to do · ParseURL and ParseStr functions ported from PHP · _CmdLine UDF easily parse command line parameters, keys or flags · AutoPHP Create documents (bills, incomes) from HTML by sending variables/arrays from AutoIt to PHP · (Un)Serialize Convert arrays and data into a storable string (PHP compatible) · RTTL Plays and exports to MP3 Nokia-format monophonic ringtones (for very old cellphones) · I18n library Simple and easy to use localization library · Scripting.Dictionary OOP and OOP-like approach · Buffer/stack limit arrays to N items by removing the last one once the limit is reached · NGBioAPI UDF to work with Nitgen fingerprint readers · Serial/Licensing system require license key based on unique machine ID from your users · HTTP a simple WinHTTP library that allows GET, POST and file uploads · Thread true AutoIt threads (under-dev) Classes _WKHtmlToX uses wkhtmlto* to convert HTML files and webpages into PDF or images (jpg, bmp, gif, png...) Snippets _Word_DocFindReplaceByLongText replace strings using Word UDF with strings longer than 255 characters (MSWord limit) rangeparser parser for printing-like pages interval (e.g.: "1,2,3-5") EnvParser parse strings/paths with environment variables and get full path Random stuff Super Mario beep sound your ears will hurt

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • hcI
      By hcI
      Hello everyone !
      I was looking for a parameter to set a List. Not a ComboList in ReadOnly.
      I've already found a topic about The readonly on a ComboList :
      But nothing on List
      Does someone know how to ?..
    • Vivaed
      By Vivaed
      I am trying to read all the files in a folder, then whatever file is newest, keep only that one and delete the rest.
      Example files:  (these all have version numbers embedded in them, I dont want to rely on the file name)
      What I have so far:
      #include <File.au3> RemoveOldFiles() ConsoleWrite(FileGetVersion("C:\WB Resources\FAINT_DONT_LINK_THESE\Faint-v4.0.0.exe") &@CRLF) Func RemoveOldFiles() Local $aFileList = _FileListToArray("C:\WB Resources\FAINT_DONT_LINK_THESE\", "*.exe",$FLTA_FILES) For $i = 0 To UBound($aFileList) - 1 $aFileVersion = FileGetVersion($aFileList[$i]) ConsoleWrite($aFileList[$i] & @CRLF) ConsoleWrite($aFileVersion & @CRLF) Next EndFunc OUTPUT: >Running:(\Program Files (x86)\AutoIt3\autoit3_x64.exe "C:\Users\bot\ownCloud\WellBeats\Delete Old Files\delete-test.au3" --> Press Ctrl+Alt+Break to Restart or Ctrl+Break to Stop 3 a.exe b.exe Faint-v4.0.0.exe <-- This is the correct file version.... +>07:34:26 AutoIt3.exe ended.rc:0 +>07:34:26 AutoIt3Wrapper Finished. >Exit code: 0 Time: 0.6647 Not sure what I am missing here?
    • david1337
      By david1337
      Hey guys
      I need help to get further with this script
      Test.txt contains lines like this:
      I have managed to view the content of a txt file in the left side of a GUI like this:
      #Include <File.au3> #include <GUIConstants.au3> Global $file = FileRead("Test.txt") GUICreate("", 800, 800, 192, 124) $control = GUICtrlCreateEdit($file, 0, 0, 400, 800, $ES_AUTOVSCROLL + $WS_VSCROLL + $ES_READONLY) GUICtrlSetFont(-1, 14, 400, 0, "@Arial Unicode MS") GUICtrlSetBkColor(-1, 0xFFFFFF) GUICtrlSetState($control, $GUI_FOCUS) ;Makes sure that text is not highlighted by default GUISetState(@SW_SHOW) While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd  
      Okay so is it possible to make each line become a clickable item?
      Say I want to delete Line2, then I highlight it and click a "remove" button.
      Also an "add" button would be needed to add new lines
      On Case $GUI_EVENT_CLOSE the changes should be saved to Test.txt (Or with a save button)
      Is this possible?
      I hope you can help me :-)

    • Rapidnxit
      By Rapidnxit
      Hi! I want to send by mail some files with a certain extension (.xml in my case). These files are located in the script folder. First, I thought to use _FileListToArrayRec function to have a list of these files. But than I don't know how to send them all at once. I know that I can attach multiple files in this way: path1;path2;path3; etc.  and so I have tried to make a string of this type with the path of the files (with a for loop) but It doesn't attach any file (only instructions.txt). How could I do? ( what I did is just an idea, if there's something better that would be great) Thanks!
      $aArrayXml = _FileListToArrayRec(@ScriptDir, "*.xml", $FLTAR_FILES) _ArrayDisplay($aArrayXml, "LIST XML") $LenghtArrayXml = UBound($aArrayXml) If ($LenghtArrayXml > 2) Then For $i = 2 To $LenghtArrayXml - 1 $temp = "&@ScriptDir&""\"&$aArrayXml[$i]&";"&"""" $XmlListFile = $XmlListFile & $temp Next EndIf $XmlListFile = StringTrimLeft($XmlListFile, 1) if($LenghtArrayXml = 2)Then $rc =_INetSmtpMailCom($s_SmtpServer, $s_FromName, $s_FromAddress, $s_ToAddress, $s_Subject, $as_Body, @ScriptDir&"\"&$aArrayXml[1]&";"&@ScriptDir&"\instructions.txt", $s_CcAddress, $s_BccAddress, $s_Username, $s_Password, $IPPort, $ssl) Else $rc = _INetSmtpMailCom($s_SmtpServer, $s_FromName, $s_FromAddress, $s_ToAddress, $s_Subject, $as_Body, @ScriptDir&"\"&$aArrayXml[1]&$XmlListFile&@ScriptDir&"\instructions.txt", $s_CcAddress, $s_BccAddress, $s_Username, $s_Password, $IPPort, $ssl) EndIf  
    • jloyzaga
      By jloyzaga
      I'd just like to find an example of a multi select list box that outputs the selections to a file. Finding lots of complex examples in examples folder and cannot find and simple ones. like simple single select list box. 
      I'm trying to put together a selection criteria. where listbox 1 has a list of environment names - when selected it will open up another control (overlay is good to cover first GUI) it then lists Applications. When selected I will use the selection to list some items from excel as a multi select list box. So are there simple examples of these that i can look at and use to create a gui that I can understand?