Jump to content

Buffer/stack with Arrays (limiting array size) UDF


Jefrey
 Share

Recommended Posts

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)
_ArrayDisplay($aBuffer)

; 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)
_ArrayDisplay($aBuffer)
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')
_ArrayDisplay($aBuffer)
_BufferReset($aBuffer)
_ArrayDisplay($aBuffer)

; 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.")
EndIf
If _BufferCheckValue($aBuffer, 'Music 2') Then ; True
   MsgBox(0, "", "Music 2 was played too recently.")
EndIf

The lib source code:

#include-once

#cs
   Buffer/stack/heap UDF
   made by Jefrey <jefrey[at]jefrey.ml>
   Licensed under WTFPL: http://www.wtfpl.net/txt/copying/
#ce

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

; 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]
      Next
   Else
      $aBuffer[0] += 1
   EndIf
   $aBuffer[$aBuffer[0]] = $mItem
   Return $aBuffer
EndFunc

; 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
EndFunc

; 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]
EndFunc

; 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]]
EndFunc

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

; 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
EndFunc

; 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
   Next
   $aBuffer[0] = 0
EndFunc

; 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
   Next
   Return 0
EndFunc

 

Edited by Jefrey
_BufferCheckValue added

My stuff

Spoiler

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) · RC4 RC4 encryption compatible with PHP and JS ·  storage.au3 localStorage and sessionStorage for AutoIt 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 GUICtrlStaticMarquee static text scrolling Random stuff Super Mario beep sound your ears will hurt

 

Link to comment
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
 Share

×
×
  • Create New...