View Javadoc
1   package eu.simuline.octave;
2   
3   import java.util.Collection;
4   import java.util.HashSet;
5   import java.util.Random;
6   
7   import java.util.regex.Pattern;
8   
9   import java.nio.charset.Charset;
10  
11  import eu.simuline.octave.type.OctaveCell;
12  import eu.simuline.octave.type.OctaveString;
13  
14  /**
15   * Small utility functions that can be used with JavaOctave.
16   * 
17   * Holder class for static functions.
18   */
19  public final class OctaveUtils {
20  
21      /**
22       * A variable name not to be listed by {@link #listVars(OctaveEngine)}. 
23       */
24      private static final String NARGIN = "__nargin__";
25  
26      /**
27       * A variable name not to be listed by {@link #listVars(OctaveEngine)}. 
28       */
29      private static final String ANS    = "ans";
30  
31      private static final Random RANDOM = new Random();
32  
33      private OctaveUtils() {
34          throw new UnsupportedOperationException("Do not instantiate");
35      }
36  
37  
38      /**
39       * Returns the charset UTF-8 used throughout. 
40       */
41      public static Charset getUTF8() {
42  	return Charset.forName("UTF-8");
43      }
44  
45      /**
46       * @param octave
47       * @return list of variables
48       */
49      @edu.umd.cs.findbugs.annotations.SuppressWarnings
50      (value = "VA_FORMAT_STRING_USES_NEWLINE", 
51       justification = "Format string evaluates in octave independent of os. ")
52      public static Collection<String> listVars(final OctaveEngine octave) {
53          final String varName = randomVarName();
54  	String evalStr = // %1 is varName 
55  	    "%1$s = cell(0, 1);\n" + 
56  	    "if strncmp(OCTAVE_VERSION(), \"3.0.\", 4)\n" + 
57  	    "  %1$s_1 = whos -v;\n" + // version 3.0
58  	    "else\n" + 
59  	    "  %1$s_1 = whos;\n" + // version 3.2 (and other)
60  	    "endif\n" + 
61  	    "for %1$s_2 = 1 : numel(%1$s_1)\n" + 
62  	    "  %1$s{%1$s_2} = %1$s_1(%1$s_2).name;\n" + 
63  	    "endfor\n" + 
64  	    "clear %1$s_1 %1$s_2\n";
65          octave.eval(String.format(evalStr, varName));
66          final OctaveCell data = octave.get(OctaveCell.class, varName);
67          octave.eval("clear " + varName);
68          final Collection<String> collection = new HashSet<String>();
69          final Pattern pattern = Pattern.compile("javaoctave_[0-9a-f]{12}_eval");
70          for (int i = 1; i <= data.getSize(2); ++i) {
71              final String name = data.get(OctaveString.class, 1, i).getString();
72              if (varName.equals(name) || 
73  		NARGIN .equals(name) || 
74  		ANS    .equals(name) || 
75  		pattern.matcher(name).matches()) {
76                  continue;
77              }
78              collection.add(name);
79          }
80          return collection;
81      }
82  
83      @SuppressWarnings("checkstyle:magicnumber")
84      // 30 is some number, compromize between security and performance 
85      private static synchronized int nextInt() {
86          return RANDOM.nextInt(1 << 30);
87      }
88  
89  
90      /**
91       * Returns a variable with value not accessible. 
92       *
93       * @return a <code>String</code> value
94       */
95      private static String randomVarName() {
96          return String.format("_OctaveUtils_%d", nextInt());
97      }
98  
99  }