[Home]

Summary:ASTERISK-05820: [FEATURE] Array Variable handling added
Reporter:crich (crich)Labels:
Date Opened:2005-12-12 09:47:17.000-0600Date Closed:2005-12-19 17:56:20.000-0600
Priority:MajorRegression?No
Status:Closed/CompleteComponents:Core/NewFeature
Versions:Frequency of
Occurrence
Related
Issues:
Environment:Attachments:( 0) res_arrays.patch.txt
Description:This Patch adds the possibility of handling arrays in the dialplan. Arrays are hereby just Varibles with names like: ${VARNAME[Idx]}. Those Variables are treated as special variables by these applications/functions.

The new Apps are:

ArraysExplode(ArrayName|ArrayData|delim)
--------------------------------------------
Creates a Variable Array of the ArrayData String, where the elements
are delimited by delim.
ArrayName      -- Name of the resulting Array Variable
ArrayData      -- String which holds the Array Data
delim  -- Delimiter

ArraysImplode(StringName|ArrayName|delim)
--------------------------------------------
Creates a String Variable of the ArrayData, where the elements
are delimited by delim.
StringName     -- Name of the resulting String Variable
ArrayName      -- Name of the Array
delim  -- Delimiter



ArraysRemoveIdx(ArrayName|idx)
---------------------------------
Removes the idx'th element of the array
ArrayName      -- Name of the Array
Idx            -- Index


These new Functions are added:

[Syntax]
ARRAYLEN(<array>)

[Synopsis]
Returns the Number of Elements in the given Array

[Syntax]
ARRAYGETINDEX(<array>|<value>)

[Synopsis]
Returns the first Index of the element which has the given Value


My intention for this is to make it possible to create a next dimension for the astdb. It's for example possible with these applications to have a database of extensions, where each extensions can have up to N-Phones which ring when it is called. The user can easily  add/remove phones via the dialplan. These Remove/Add Transactions are hardly coverable by extensions.{conf,ael}.

It would be possible to create agi scripts for that, but it is really useful to treat variables as arrays in the dialplan sometimes.

Comments:By: Tilghman Lesher (tilghman) 2005-12-12 10:39:21.000-0600

You can already do most of this with existing functions:

CUT(), FIELDQTY()

By: Tilghman Lesher (tilghman) 2005-12-12 10:43:02.000-0600

And see ASTERISK-5752 for another piece, already done.

By: Tilghman Lesher (tilghman) 2005-12-12 10:46:17.000-0600

Additionally, res_* is reserved for modules which run threads in the background, but aren't actually channels.  Something that implements only apps or funcs should go into one of those respective directories.

By: crich (crich) 2005-12-12 10:47:47.000-0600

Yeah I've tried that, thats the reason why i choosed to implement additional applications/functions for that.

The point is that its likely to make bugs in the dialplan, this ressource encapsulates some of the crucial looping/adding/removeing of arraylements.

If every user needs to implement them e.g. as macros with the dialplan, every (experienced) user needs about 4-8 hours for that i believe. Then the dialplan is quite full with stuff which doesn't actually match the real needs.

Lets assume 100 Users need this 100*5hours ==500hours wasteing time with implementing these functions with dialplan for/while loops ;)

By: crich (crich) 2005-12-12 10:53:06.000-0600

I choosed res because it installs apps and funcs so where to put it ?

anyway ASTERISK-5752 is just Set isn't it ?

Set already supports setting multiple variables.

By: Tilghman Lesher (tilghman) 2005-12-12 10:56:50.000-0600

I understand your intent, but we've tried hard to make functions and applications that are as generic as possible, to be able to be used in the widest number of situations.

If you want to create a set of widely used subroutines, with either Macro or Gosub, and put those on the Wiki or in the documentation, I think that would be a great contribution.



By: Tilghman Lesher (tilghman) 2005-12-12 11:05:11.000-0600

ASTERISK-5752 is only to be used with Set, and the syntax is different from what Set currently allows:

Set(var1=val1,var2=val2)
Set(ARRAY(var1,var2)=val1,val2)

Multiple lines can be made into one:
Set(var1=${CUT(something,\,,1)})
Set(var2=${CUT(something,\,,2)})

Set(ARRAY(var1,var2)=${CUT(something,\,,1-2)})

By: crich (crich) 2005-12-12 11:13:13.000-0600

Well I thought that haveing a more advanced Variable type, with the possibilities of:

* saving/loading them either in the astdb or in a file
* posting them as UserEvents,

and the needed mangling Functions, would exactly meet the case of generic functions.

Also they interface quite prefectly with every other Diaplan related stuff.

Assume the following example which may clarify the generality of these functions (written in ael):

* => {
DBget(phone=SIP/crich1&mISDN/1/15&Zap/g1/1234);
ArraysExplode(arr,${phones},&);
i=0;
Dial(${arr[${i}]||1);
Dial(${arr[$[${i}+1]]||1);
Dial(${arr[$[${i}+2]]||1);
};

The other Example is

* => {
phone[0]=SIP/crich;
phone[1]=SIP/cory;

ArraysImplode(tmp,phone,\,);
DBput(exten-crich/phones=${tmp});
};


with the rest of the functions it is easy to remove elements of the array. adding is just Setting them.

By: crich (crich) 2005-12-12 11:18:28.000-0600

Ok you're right the explode stuff is already done by your patch, but the implode stuff would'nt work that way.

By: Tilghman Lesher (tilghman) 2005-12-12 11:21:48.000-0600

implode is basically:

Set(foo=${bar[1]}\,${bar[2]}\,${bar[3]})

By: Tilghman Lesher (tilghman) 2005-12-12 11:23:03.000-0600

Oh, and DBGet is gone from the trunk.  Ditto for DBPut.  You need to learn to use the DB function.



By: crich (crich) 2005-12-12 11:29:37.000-0600

hehe you got me then Implode's quite easy ..

Can we expect your Array() - Stuff to get into the trunk anywhen ?

Still we'll need something like Unset(varname) to make my patch completely redundant i believe.

By: crich (crich) 2005-12-12 11:32:57.000-0600

Btw. thx for your tip about the DB functions, i already knew that but wasn't brave enough to modify my dialplans ; )

By: Tilghman Lesher (tilghman) 2005-12-12 11:38:28.000-0600

You can just set a var to the empty string.  While this doesn't completely make the variable go away, it interpolates as exactly the same thing as an undeclared variable:

Set(foo=)

By: crich (crich) 2005-12-12 14:10:19.000-0600

You've convinced me too fast, I didn't thought about the side effects.

Implode/Explode are quite different to Set/Array

while doing implode with set you need to pass all the vars var1..varN while at using Implode you need only to pass one name of the whole arraybundle! This is quite an important difference.

The same goes for Set(Array()=Cut()); you need to know the amount of Fields, you can find that out by FIELDQTY of course, but still you need to merge the String you pass to Array(), this needs a Loop in my opinion. With Implode you do not need this loop.

By: Tilghman Lesher (tilghman) 2005-12-12 22:46:13.000-0600

I don't necessarily agree with storing array elements separately.  I think they should all be stored in a single variable, and split them out as necessary, when you need a single element.  This behaves in a more expected way (i.e. when you delete an array item, you don't get a gap; you get all the array indexes to the right of that element automatically moved).  Similarly, you get appropriate behavior when you insert an item into the array.

If you dispose of the idea that you need to have elements broken out into separate variables, then there's no need for explode/implode.  Just separate them out at the exact time you need to use each, and be done with it.

By: crich (crich) 2005-12-13 04:27:03.000-0600

Sometimes it is usefull to have the array-like view. Lets say you want to create a from phone settable features set like:

feature[1]=dnd
feature[2]=cfwd
..
feature[n]=toggleQueueMembership

then you can have an extension like:

*X*XX => {
 feature=${EXTEN:1:1};
 userExten=${EXTEN:3};

 &toggle-db-flag-macro(${feature[${feature}]},${userExten});
 SayAlpha(${feature[${feature}]});
 Playback(toggled);
};


where toggle-db-flag toggles the feature for each extension to either 1 or 0 by each call.

Other examples are to store multiple Phones where the user is reachable in an array and save the in the astdb, in the array view it is with my functions very easy to append new phones or delete existing ones, without thinking about the gap problem, because this is already implemented in the functions.

By: crich (crich) 2005-12-19 16:10:29.000-0600

After some rethinking, i find that it is indeed easy to hold quantities in delimited strings. Especially with $[ expr : regexp ] one can easily modify/delete/add items from delimited strings.

I will provide some macros on wiki or somewhere, so other don't neet to handle with the regexp stuff.

So i think you can close this issue.