Y-lib
Loadrunner libraries
y_param_array.c
Go to the documentation of this file.
1 /*
2  * Ylib Loadrunner function library.
3  * Copyright (C) 2005-2014 Floris Kraak <randakar@gmail.com> | <fkraak@ymor.nl>
4  * Copyright (C) 2009 Raymond de Jongh <ferretproof@gmail.com> | <rdjongh@ymor.nl>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
36 #ifndef _Y_PARAM_ARRAY_C_
37 #define _Y_PARAM_ARRAY_C_
39 
41 #include "vugen.h"
42 #include "y_string.c"
43 #include "y_loadrunner_utils.c"
44 
46 
47 
67 #ifdef Y_COMPAT_LR_8
68 int y_array_count( const char *param_array )
69 {
70  int result;
71  size_t size = strlen(param_array) +9; // 9 = strlen("{}_count") +1 -- the +1 is '\0'
72  char *tmp = y_mem_alloc(size);
73 
74  snprintf(tmp , size, "{%s_count}" , param_array );
75  result = atoi(lr_eval_string(tmp));
76  free(tmp);
77  return result;
78 }
79 #else
80 #define y_array_count( param_array ) lr_paramarr_len(param_array)
81 #endif // Y_COMPAT_LR_8
82 
83 
107 #ifdef Y_COMPAT_LR_8
108 char *y_array_get( const char *source_param_array, const int param_array_index )
109 {
110  int size = y_array_count( source_param_array );
111  char *tmp;
112  char *result;
113 
114  //lr_log_message("y_array_get(%s,%d)", source_param_array, param_array_index );
115  if ( (param_array_index > size) || (param_array_index < 1) )
116  {
117  lr_error_message("Index out of bounds");
118  lr_abort();
119  return NULL;
120  }
121 
122  // Calculate space requirements
123  {
124  size_t bufsize = strlen(source_param_array)+y_int_strlen(param_array_index)+4; // strlen() + size of index + {}_\0
125  tmp = y_mem_alloc(bufsize);
126  snprintf( tmp , bufsize, "{%s_%d}" , source_param_array , param_array_index );
127  }
128 
129  result = lr_eval_string(tmp);
130  free (tmp);
131  return result;
132 }
133 #else
134 #define y_array_get( source_param_array, param_array_index ) lr_paramarr_idx(source_param_array, param_array_index)
135 #endif // Y_COMPAT_LR_8
136 
137 
180 char* y_array_get_no_zeroes( const char *source_param_array, const int param_array_index )
181 {
182  if ( (param_array_index > y_array_count(source_param_array)) || (param_array_index < 1) )
183  {
184  lr_error_message("Parameter array %s does not exist or index %d out of bounds.", source_param_array, param_array_index);
185  lr_abort();
186  return NULL;
187  }
188  else
189  {
190  // Calculate space requirements
191  size_t bufsize = strlen(source_param_array) + y_int_strlen(param_array_index) +2; // strlen() + _\0
192  char* tmp = y_mem_alloc(bufsize);
193  snprintf(tmp, bufsize, "%s_%d", source_param_array, param_array_index );
194  return y_get_cleansed_parameter(tmp, ' '); // <-- Might want to make that configurable..
195  }
196 }
197 
217 void y_array_save(const char* value, const char* source_param_array, const int param_array_index)
218 {
219  if(source_param_array == NULL)
220  {
221  // In some cases calling this without a parameter name is entirely valid.
222  // eg. y_split() on an array where you only need one half of the results.
223  return;
224  }
225  else
226  {
227  int len = strlen(source_param_array) + y_int_strlen(param_array_index) +2; // +2 = _\0
228  char *result = y_mem_alloc(len);
229  snprintf(result, len, "%s_%d", source_param_array, param_array_index);
230  lr_save_string(value, result);
231  free(result);
232  }
233 }
234 
246 void y_array_save_count(const int count, const char *source_param_array)
247 {
248  if( source_param_array == NULL )
249  {
250  // In some cases calling this without a parameter name is entirely valid.
251  // eg. y_split() on an array where you only need one half of the results.
252  return;
253  }
254  else
255  {
256  int len = strlen(source_param_array) +7; // 7 = strlen("_count") +1, where +1 would be the '\0' byte at the end.
257  char* result = y_mem_alloc(len);
258 
259  snprintf(result, len, "%s_count", source_param_array);
260  lr_save_int(count, result);
261  free(result);
262  }
263 }
264 
282 void y_array_add( const char* source_param_array, const char* value )
283 {
284  int size = y_array_count(source_param_array) +1;
285  y_array_save(value, source_param_array, size);
286  y_array_save_count(size, source_param_array);
287 }
288 
305 void y_array_concat(const char *source_param_array_first, const char *source_param_array_second, const char *result_array)
306 {
307  int size_first = y_array_count(source_param_array_first);
308  int size_second = y_array_count(source_param_array_second);
309  int size_total = size_first + size_second;
310  int i = 1;
311  int j = 1;
312 
313  //lr_log_message("y_array_concat(%s, %s, %s)", source_param_array_first, source_param_array_second, result_array);
314  //lr_log_message("size_total = %d, i = %d", size_total, i);
315 
316  for(i=1; i <= size_total; i++)
317  {
318  char *value;
319  //lr_log_message("Iteration %i, j=%d", i, j);
320 
321  if( i <= size_first )
322  {
323  value = y_array_get_no_zeroes(source_param_array_first,i);
324  }
325  else
326  {
327  value = y_array_get_no_zeroes(source_param_array_second,j);
328  j++;
329  }
330 
331  y_array_save(value, result_array, i);
332  lr_eval_string_ext_free(&value);
333  }
334  y_array_save_count(size_total, result_array);
335 }
336 
337 
351 char *y_array_get_random( const char *source_param_array )
352 {
353  int count = y_array_count( source_param_array );
354  if( count < 1 )
355  {
356  lr_log_message("No elements found in parameter array!");
357  return NULL;
358  }
359 
360  _y_random_array_index= (y_rand() % count) +1;
361  return y_array_get(source_param_array, _y_random_array_index);
362 }
363 
364 
378 char *y_array_get_random_no_zeroes( const char *source_param_array )
379 {
380  int count = y_array_count( source_param_array );
381  if( count < 1 )
382  {
383  lr_log_message("No elements found in parameter array!");
384  return NULL;
385  }
386 
387  _y_random_array_index = (y_rand() % count) +1;
388  return y_array_get_no_zeroes(source_param_array, _y_random_array_index);
389 }
390 
391 
402 int y_array_pick_random( const char *source_param_array )
403 {
404  if(y_array_count(source_param_array))
405  {
406  char *result = y_array_get_random_no_zeroes(source_param_array);
407  lr_save_string(result, source_param_array);
408  lr_eval_string_ext_free(&result);
409  return _y_random_array_index;
410  }
411  else
412  {
413  lr_save_string("", source_param_array);
414  //lr_output_message("y_array_pick_random(): Unknown parameter list");
415  return 0;
416  }
417 }
418 
431 void y_array_dump( const char *source_param_array )
432 {
433  int i;
434  int count;
435 
436  for ( i=1 ; i <= y_array_count(source_param_array); i++ )
437  {
438  char *msg = y_array_get_no_zeroes(source_param_array, i);
439  lr_output_message("{%s_%d} = %s" , source_param_array, i, msg);
440  lr_eval_string_ext_free(&msg);
441  }
442 }
443 
444 
482 void y_array_save_param_list(const char *sourceParam, const char *LB, const char *RB, const char *result_array)
483 {
484  int i = 0;
485  char *source = y_get_parameter(sourceParam);
486  int buflen = strlen(source)+1;
487  char *buffer = y_mem_alloc(buflen);
488  char *next = buffer;
489  memcpy(buffer, source, buflen);
490 
491  while( next = (char *)strstr(next, LB) )
492  {
493  char* end = strstr(next, RB);
494  if(!end)
495  break;
496  buffer[end - buffer] = '\0';
497 
498  i++;
499  y_array_save(next+strlen(LB), result_array, i);
500  next = end + strlen(RB);
501  }
502  free(buffer);
503  y_array_save_count(i, result_array);
504 }
505 
525 void y_array_grep( const char *source_param_array, const char *search, const char *result_array)
526 {
527  int i, j = 1;
528  char *item;
529  int size = y_array_count(source_param_array);
530 
531  for( i=1; i <= size; i++)
532  {
533  item = y_array_get_no_zeroes(source_param_array, i);
534  if( strstr(item, search) )
535  {
536  y_array_save(item, result_array, j++);
537  }
538  lr_eval_string_ext_free(&item);
539  }
540  y_array_save_count(j-1, result_array);
541 }
542 
562 void y_array_filter( const char *source_param_array, const char *search, const char *result_array)
563 {
564  int i, j = 1;
565  char *item;
566  int size = y_array_count(source_param_array);
567 
568  for( i=1; i <= size; i++)
569  {
570  item = y_array_get_no_zeroes(source_param_array, i); // Some pages contain a null byte - \x00 in the input. Ugh.
571  if( strstr(item, search) == NULL )
572  {
573  y_array_save(item, result_array, j++);
574  }
575  lr_eval_string_ext_free(&item);
576  }
577  y_array_save_count(j-1, result_array);
578 }
579 
580 
612 int y_array_merge(const char *param_array_left, const char *param_array_right, const char *separator, const char *result_array)
613 {
614  int i = 1;
615  char *param;
616  int length = y_array_count(param_array_left);
617  int seperator_size = strlen(separator);
618 
619  if( length != y_array_count(param_array_right) )
620  {
621  // If the sizes aren't the same there's a good chance numbers won't line up on both sides.
622  // We definitely don't want to end up with records merged that don't actually correspond to each other!
623  lr_error_message("Unable to merge arrays %s and %s - sizes unequal!", param_array_left, param_array_right);
624  lr_abort();
625  return 0;
626  }
627 
628  for( i=1; i <= length; i++)
629  {
630  char *left = y_array_get_no_zeroes(param_array_left, i);
631  char *right = y_array_get_no_zeroes(param_array_right, i);
632  size_t size = strlen(left)+seperator_size+strlen(right)+1;
633  char *result = y_mem_alloc(size);
634 
635  snprintf(result, size, "%s%s%s", left, separator, right);
636  lr_eval_string_ext_free(&left);
637  lr_eval_string_ext_free(&right);
638  y_array_save(result, result_array, i);
639  free(result);
640  }
641  y_array_save_count(i-1, result_array);
642  return 1;
643 }
644 
645 
646 
647 
662 void y_array_split(const char *source_param_array, const char *separator, const char *param_array_left, const char *param_array_right)
663 {
664  int i = 1;
665  int size = y_array_count(source_param_array);
666 
667  //lr_log_message("y_array_split(%s, %s, %s, %s)", source_param_array, separator,param_array_left, param_array_right);
668 
669  for( i=1; i <= size; i++)
670  {
671  char *item = y_array_get_no_zeroes(source_param_array, i);
672  int len = strlen(item);
673  char *left = y_mem_alloc(len);
674  char *right = y_mem_alloc(len);
675 
676  left[0] = '\0';
677  right[0] = '\0';
678 
679  y_split_str(item, separator, left, right);
680  lr_eval_string_ext_free(&item);
681 
682  y_array_save(left, param_array_left, i);
683  free(left);
684  y_array_save(right, param_array_right, i);
685  free(right);
686  }
687 
688  y_array_save_count(i-1,param_array_left);
689  y_array_save_count(i-1,param_array_right);
690 }
691 
692 
715 void y_array_shuffle(char *source_param_array, char *result_array)
716 {
717  int *shuffle;
718  int source_length, i;
719 
720  if (strcmp(source_param_array, result_array) == 0)
721  {
722  lr_error_message("Source and Destination parameter name can not be equal!");
723  lr_abort();
724  return;
725  }
726 
727  source_length = y_array_count(source_param_array);
728  if(source_length < 1)
729  {
730  lr_error_message("Cannot shuffle empty parameter arrays!");
731  lr_abort();
732  return;
733  }
734  else if(source_length == 1)
735  {
736  lr_log_message("Warning: Cannot shuffle a list with just 1 entry.");
737  y_array_save( y_array_get(source_param_array, 1), result_array, 1);
738  y_array_save_count(1, result_array);
739  return;
740  }
741 
742  // Now the cases where we can actually shuffle something:
743  shuffle=(int *)y_array_alloc(source_length+1, sizeof(int)); // Allocate room for an array of ints.
744  for (i=1; i<=source_length; i++) // Fill it with the numbers 1 .. source length, denoting indexes into the source array, unshuffled.
745  {
746  //lr_message("i: %d", i);
747  shuffle[i]=i;
748  }
749 
750  // For each item in that list of ints, have it swap places with a randomly chosen item from that same list. (Switching with yourself is legal.)
751  for(i=1; i<=source_length; i++)
752  {
753  int temp, r;
754  r=(y_rand() % (source_length))+1;
755  lr_log_message("shuffle r %d into i %d", r, i);
756  lr_log_message("swapping %d with %d", shuffle[i], shuffle[r]);
757  temp = shuffle[i];
758  shuffle[i] = shuffle[r];
759  shuffle[r] = temp;
760  }
761 
762  // Now that we have a list of shuffled numbers, use those numbers to store the elements in the source parameter array into the corresponding slots of the destination.
763  for(i=1; i<=source_length; i++)
764  {
765  y_array_save(
766  y_array_get(source_param_array, shuffle[i]),
767  result_array, i);
768  }
769  y_array_save_count(--i, result_array); // We can probably just use the source_length here instead.
770  free (shuffle);
771 }
772 
773 #endif // _Y_PARAM_ARRAY_C_
Y-lib string function library.
void y_array_save_param_list(const char *sourceParam, const char *LB, const char *RB, const char *result_array)
Create a parameter list from a single parameter value.
void y_array_add(const char *source_param_array, const char *value)
int y_array_merge(const char *param_array_left, const char *param_array_right, const char *separator, const char *result_array)
void y_array_concat(const char *source_param_array_first, const char *source_param_array_second, const char *result_array)
Concatenate two arrays together and save the result into a third array.
#define y_array_get(source_param_array, param_array_index)
Fetch the content of a specific element from a parameter list based on index.
Standard C function headers.
int _y_random_array_index
Definition: y_param_array.c:45
void y_array_save_count(const int count, const char *source_param_array)
char * y_array_get_no_zeroes(const char *source_param_array, const int param_array_index)
Get the content the nth member of target parameter array, but without embedded zeroes.
void y_array_save(const char *value, const char *source_param_array, const int param_array_index)
Save a string value into an array at a specified position.
void y_array_filter(const char *source_param_array, const char *search, const char *result_array)
Search a parameter array for a specific string and and build a new result array containing only param...
char * strstr(const char *string1, const char *string2)
Documented at http://www.cplusplus.com/reference/cstring/strstr/.
char * y_mem_alloc(size_t size)
Ylib wrapper for malloc()
Definition: y_core.c:221
char * y_array_alloc(size_t length, size_t size)
Allocates a character array and initializes all elements to zero As y_mem_alloc(), but using the &#39;calloc&#39; function, rather than &#39;malloc()&#39;.
Definition: y_core.c:245
void * memcpy(void *dest, const void *src, size_t n)
Documented at http://www.cplusplus.com/reference/cstring/memcpy/.
char * y_array_get_random(const char *source_param_array)
Get a random element from a parameter list.
int atoi(const char *string)
Documented at http://www.cplusplus.com/reference/cstdlib/atoi/.
int strcmp(const char *string1, const char *string2)
Documented at http://www.cplusplus.com/reference/cstring/strcmp/.
void y_array_dump(const char *source_param_array)
Dump the contents of a list of saved parameters to standard output (the run log)
char * y_get_cleansed_parameter(const char *param_name, char replacement)
Get the content of a parameter without embedded null bytes (\0 characters) from the named parameter...
Definition: y_string.c:868
void y_array_split(const char *source_param_array, const char *separator, const char *param_array_left, const char *param_array_right)
char * y_array_get_random_no_zeroes(const char *source_param_array)
Get a random element from a parameter list without embedded zeroes.
#define y_array_count(param_array)
Determine the number of elements in the target parameter array.
Definition: y_param_array.c:80
size_t strlen(const char *string)
Documented at http://www.cplusplus.com/reference/cstring/strlen/.
Collection of miscellaneous support functions.
int y_array_pick_random(const char *source_param_array)
Choose an element at random from a saved parameter list and store it in a parameter with the same nam...
int snprintf(char *buffer, size_t n, const char *format_string,...)
Documented at http://www.cplusplus.com/reference/cstdio/snprintf/. This function was introduced by t...
long y_rand(void)
Generate a random (integer) number between 0 and Y_RAND_MAX (30 bit maxint).
Definition: y_core.c:156
char * y_get_parameter(const char *param_name)
Get the content of a parameter and return it as a char *.
Definition: y_core.c:336
void y_array_shuffle(char *source_param_array, char *result_array)
void y_array_grep(const char *source_param_array, const char *search, const char *result_array)
Search a parameter array for a specific text and build a new array containing only parameters contain...
void y_split_str(const char *original, const char *separator, char *left, char *right)
Split a string into 2 parts based on a search string.
Definition: y_string.c:341
void free(void *mem_address)
Documented at http://www.cplusplus.com/reference/cstdlib/free/.