CodeSonar C++ API
[For improved navigation, enable JavaScript.]
cs_xref.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2023, an unpublished work by CodeSecure, Inc.
3  * ALL RIGHTS RESERVED
4  *
5  * Copyright (c) 2013-2023, an unpublished work by GrammaTech, Inc.
6  * ALL RIGHTS RESERVED
7  *
8  * This software is furnished under a license and may be used and
9  * copied only in accordance with the terms of such license and the
10  * inclusion of the above copyright notice. This software or any
11  * other copies thereof may not be provided or otherwise made
12  * available to any other person. Title to and ownership of the
13  * software is retained by CodeSecure, Inc.
14  */
15 
16 #ifndef CS_XREF_HPP
17 #define CS_XREF_HPP
18 
19 #include "cs_xref.h"
20 #include "cs_xref_fwd.hpp"
21 #include "cs_sfile_decl.hpp"
22 
23 
26 namespace cs{
27 
35  class xr_tuple{
36  csuint64 namehash;
37  xr_kind_role kr;
38  bool complete;
39  sfile file;
40  line_number line;
41  sfile def_file;
42  line_number def_line;
43  xr_tuple();
44  class xr_tuple_name_helper
45  {
46  public:
48  typedef const cs_xref_tuple* ctype;
50  private:
51  xr_tuple_name_helper();
52  };
53  typedef cs_xref_tuple ctype;
54 
55  public:
63  csuint64 get_namehash() const
64  { return namehash; }
65 
66 
72  { return kr; }
73 
74 
80  bool get_complete() const
81  { return complete; }
82 
83 
88  sfile get_file() const
89  { return file; }
90 
91 
97  { return line; }
98 
99 
108  { return def_file; }
109 
110 
116  { return def_line; }
117 
118 
131  std::string get_name() const;
132 
133 
160  xr_tuple(csuint64 _namehash, xr_kind_role _kr, bool _complete,
161  sfile _file, line_number _line,
162  sfile _def_file, line_number _def_line)
163  : namehash(_namehash)
164  , kr(_kr)
165  , complete(_complete)
166  , file(_file)
167  , line(_line)
168  , def_file(_def_file)
169  , def_line(_def_line){}
170 
172  std::string as_string() const;
173 
175  std::string as_repr() const
176  { return as_string(); }
177 
188  int cmp(const xr_tuple &other) const
189  {
190  int r;
191  r = file.cmp(other.file);
192  if( r ) return r;
193  if( line < other.line )
194  return -1;
195  if( line > other.line )
196  return 1;
197  if( namehash < other.namehash )
198  return -1;
199  if( namehash > other.namehash )
200  return 1;
201  r = kr.cmp(other.kr);
202  if( r ) return r;
203  r = def_file.cmp(other.def_file);
204  if( r ) return r;
205  if( def_line < other.def_line )
206  return -1;
207  if( def_line > other.def_line )
208  return 1;
209  if( complete < other.complete )
210  return -1;
211  if( complete > other.complete )
212  return 1;
213  return 0;
214  }
215 
220  CS_BOILERPLATE_HASH_TYPE hash() const
221  {
222  return file.hash()
223  + static_cast<CS_BOILERPLATE_HASH_TYPE>(line) * 4391
224  + static_cast<CS_BOILERPLATE_HASH_TYPE>(namehash)
225  + kr.hash() * 12583
226  + def_file.hash()
227  + static_cast<CS_BOILERPLATE_HASH_TYPE>(def_line) * 997
228  + static_cast<CS_BOILERPLATE_HASH_TYPE>(complete);
229  }
230 
231  CS_CMP_COMPARATORS(xr_tuple)
232  };
233  CS_IR_BOILERPLATE_FRIENDS(xr_tuple)
234 
235 
241  inline std::ostream &operator<<( std::ostream &out, const xr_tuple &t )
242  {
243  csuint64 nh = t.get_namehash();
244  out << CS_AS_REPR_PREFIX "xr_tuple ";
245  out << std::hex
246  << ((const csuint32*)&nh)[CS_MOST_SIGNIFICANT_WORD]
247  << ((const csuint32*)&nh)[CS_LEAST_SIGNIFICANT_WORD]
248  << std::dec;
249  out << ", "
250  << t.get_kind_role().name() << ", ";
251  if( !t.get_complete() )
252  out << "incomplete, ";
253  out << t.get_file() << ":"
254  << t.get_line() << ", "
255  << t.get_def_file() << ":"
256  << t.get_def_line()
257  << CS_AS_REPR_SUFFIX;
258  return out;
259  }
260 
261  inline std::string xr_tuple::as_string() const
262  {
263  std::stringstream buf;
264  buf << *this;
265  return buf.str();
266  }
267 
268 #ifdef CSFE_API
269 #define CGLUE_NAMESPACE csfe::
270 #else
271 #define CGLUE_NAMESPACE
272 #endif
273 
274  inline std::string xr_tuple::get_name() const
275  {
276 #ifndef CSFE_API
277  cs_xref_tuple converted;
278  converted.namehash = namehash;
279  converted.kr = cglue<xr_kind_role>::unwrap(kr);
280  converted.complete = complete;
281  converted.sf = CGLUE_NAMESPACE cglue<sfile>::unwrap(file);
282  converted.line = line;
283  converted.def_sf = CGLUE_NAMESPACE cglue<sfile>::unwrap(def_file);
284  converted.def_line = def_line;
285 
286  string_scratchpad::
287  to_string_functor1_limit<xr_tuple_name_helper, &cs_xref_tuple_token>
288  functor(&converted, (size_t)-1);
289  return string_scratchpad::to_string(functor);
290 #else
291  return "<FE_TODO>";
292 #endif
293  }
294 
295 
296 #ifndef CSFE_API
297  class xr_definition_iterator_policy;
298 #endif
299  template<>
300  class cglue<xr_tuple>{
301 #ifndef CSFE_API
302  friend class iterator_adapter<xr_definition_iterator_policy>;
303  friend class iterator_adapter<xr_occurrence_iterator_policy>;
304  friend class iterator_adapter<xr_homonym_iterator_policy>;
305  friend class iterator_adapter<xr_intra_definition_iterator_policy>;
306  friend class iterator_adapter<xr_query_iterator_policy>;
307  friend class xr_query_iterator_policy_container;
308  friend class xr_definition_iterator_policy;
309  friend class xr_occurrence_iterator_policy;
310  friend class xr_homonym_iterator_policy;
311  friend class xr_intra_definition_iterator_policy;
312  friend class xr_query_iterator_policy;
313 #endif
314  public:
315  typedef xr_tuple type;
316  typedef cs_xref_tuple ctype;
317  CS_CXX_API_CGLUE_ACCESS_MODIFIER:
318  static type wrap(const ctype &c)
319  {
320  return xr_tuple(c.namehash,
321  cglue<xr_kind_role>::wrap(c.kr),
322  !!c.complete,
323  CGLUE_NAMESPACE cglue<sfile>::wrap(c.sf), c.line,
324  CGLUE_NAMESPACE cglue<sfile>::wrap(c.def_sf), c.def_line);
325  }
326  };
327 
328 #ifndef CSFE_API
329  class xr_definition_iterator_policy_container{
330  xr_definition_iterator_policy_container();
331  public:
332  sfile file;
333  line_number line;
334  csuint64 namehash;
335  xr_def_iter_flags flags;
336  xr_definition_iterator_policy_container(
337  sfile _file,
338  line_number _line,
339  csuint64 _namehash,
340  xr_def_iter_flags _flags)
341  : file(_file)
342  , line(_line)
343  , namehash(_namehash)
344  , flags(_flags){}
345  };
346 
347  class xr_definition_iterator_policy{
348  public:
349  typedef cs_xref_def_iter iterator_impl;
350  typedef xr_tuple key;
351  typedef xr_definition_iterator_policy_container ctype;
352 
353  static cs_result iter_first(
354  const ctype &container,
355  cglue<key>::ctype *val,
356  iterator_impl *it)
357  {
358  return cs_xref_def_iter_first(
359  cglue<sfile>::unwrap(container.file),
360  container.line,
361  container.namehash,
362  cglue<xr_def_iter_flags>::unwrap(container.flags),
363  val, it );
364  }
365  static cs_result iter_next(
366  const ctype &container,
367  cglue<key>::ctype *val,
368  iterator_impl *it)
369  { return cs_xref_def_iter_next( val, it ); }
370  static cs_result iter_close(iterator_impl *it)
371  { return cs_xref_def_iter_close( it ); }
372  static const char *name()
373  { return "xr_definition_iterator"; }
374  };
375 
377  class xr_occurrence_iterator_policy_container{
378  xr_occurrence_iterator_policy_container();
379  public:
380  sfile file;
381  line_number line;
382  csuint64 namehash;
383  cs_xr_kind_role kr_filter;
384  size_t limit_per_kind_role;
385  xr_occ_iter_flags flags;
386  xr_occurrence_iterator_policy_container(
387  sfile _file,
388  line_number _line,
389  csuint64 _namehash,
390  cs_xr_kind_role _kr_filter,
391  size_t _limit_per_kind_role,
392  xr_occ_iter_flags _flags)
393  : file(_file)
394  , line(_line)
395  , namehash(_namehash)
396  , kr_filter(_kr_filter)
397  , limit_per_kind_role(_limit_per_kind_role)
398  , flags(_flags){}
399  };
400 
401  class xr_occurrence_iterator_policy{
402  public:
403 #ifndef SWIG
404  class iterator_impl
405  {
406  public:
407  iterator_impl(){}
408  cs_xref_occ_iter c_iter;
409  cs_xref_result_counters counters;
410  };
411 #endif
412  typedef xr_tuple key;
413  typedef xr_occurrence_iterator_policy_container ctype;
414 
415  static cs_result iter_first(
416  ctype &container,
417  cglue<key>::ctype *val,
418  iterator_impl *it)
419  {
420  return cs_xref_occ_iter_first(
421  cglue<sfile>::unwrap(container.file),
422  container.line,
423  container.namehash,
424  container.kr_filter,
425  container.limit_per_kind_role,
426  cglue<xr_occ_iter_flags>::unwrap(container.flags) & ~csxroif_populate_counters,
427  val,
428  &it->c_iter,
430  ? &it->counters
431  : NULL,
432  /* It's not great that C++ API clients cannot take
433  * advantage of the efficiency gains available by
434  * querying for both kinds of iterators at once, but
435  * to make this work with the iterator_adapter
436  * abstraction requires a lot of extra layers of
437  * indirection.
438  */
439  NULL, NULL );
440  }
441  static cs_result iter_next(
442  ctype &container,
443  cglue<key>::ctype *val,
444  iterator_impl *it)
445  { return cs_xref_occ_iter_next( val, &it->c_iter ); }
446  static cs_result iter_close(iterator_impl *it)
447  { return cs_xref_occ_iter_close( &it->c_iter ); }
448  static const char *name()
449  { return "xr_occurrence_iterator"; }
450  };
451 
452  template<>
453  class iterator_adapter_mixin<xr_occurrence_iterator_policy>
454  {
455  typedef iterator_adapter<xr_occurrence_iterator_policy> adapter_t;
456  const cs_xref_result_counters *get_counters() const
457  {
458  const adapter_t *self = static_cast<const adapter_t*>(this);
459  if( ( self->container->flags
462  {
463  check(CS_ERROR_INVALID_ARGUMENT);
464  }
465  if( self->state == adapter_t::EMPTY
466  || self->state == adapter_t::SINGLETON )
467  {
468  check(CS_ERROR_INVALID_ARGUMENT);
469  }
470  self->at_end();
471  return &self->inner->counters;
472  }
473  protected:
474  iterator_adapter_mixin(){}
475  public:
495  size_t get_scanned_count() const
496  { return get_counters()->scanned; }
497 
498 
517  size_t get_unscanned_count() const
518  { return get_counters()->unscanned; }
519 
537  size_t get_matched_count() const
538  { return get_counters()->matched; }
539  };
540 
542  class xr_homonym_iterator_policy_container{
543  xr_homonym_iterator_policy_container();
544  public:
545  sfile file;
546  line_number line;
547  csuint64 namehash;
548  cs_xr_kind_role kr_filter;
549  size_t limit_per_kind_role;
550  xr_occ_iter_flags flags;
551  xr_homonym_iterator_policy_container(
552  sfile _file,
553  line_number _line,
554  csuint64 _namehash,
555  cs_xr_kind_role _kr_filter,
556  size_t _limit_per_kind_role,
557  xr_occ_iter_flags _flags)
558  : file(_file)
559  , line(_line)
560  , namehash(_namehash)
561  , kr_filter(_kr_filter)
562  , limit_per_kind_role(_limit_per_kind_role)
563  , flags(_flags){}
564  };
565 
566  class xr_homonym_iterator_policy{
567  public:
568 #ifndef SWIG
569  class iterator_impl
570  {
571  public:
572  iterator_impl(){}
573  cs_xref_occ_iter c_iter;
574  cs_xref_result_counters counters;
575  };
576 #endif
577  typedef xr_tuple key;
578  typedef xr_homonym_iterator_policy_container ctype;
579 
580  static cs_result iter_first(
581  ctype &container,
582  cglue<key>::ctype *val,
583  iterator_impl *it)
584  {
585  cs_result r = cs_xref_occ_iter_first(
586  cglue<sfile>::unwrap(container.file),
587  container.line,
588  container.namehash,
589  container.kr_filter,
590  container.limit_per_kind_role,
591  cglue<xr_occ_iter_flags>::unwrap(container.flags) & ~csxroif_populate_counters,
592  val, NULL, NULL,
593  &it->c_iter,
595  ? &it->counters
596  : NULL );
597  switch( r )
598  {
599  case CS_SUCCESS:
600  case CS_OUT_OF_ELEMENTS:
601  return iter_next(container, val, it);
602  default:
603  return r;
604  }
605  }
606  static cs_result iter_next(
607  ctype &container,
608  cglue<key>::ctype *val,
609  iterator_impl *it)
610  { return cs_xref_occ_iter_next( val, &it->c_iter ); }
611  static cs_result iter_close(iterator_impl *it)
612  { return cs_xref_occ_iter_close( &it->c_iter ); }
613  static const char *name()
614  { return "xr_homonym_iterator"; }
615  };
616 
618  template<>
619  class iterator_adapter_mixin<xr_homonym_iterator_policy>
620  {
621  typedef iterator_adapter<xr_homonym_iterator_policy> adapter_t;
622  const cs_xref_result_counters *get_counters() const
623  {
624  const adapter_t *self = static_cast<const adapter_t*>(this);
625  if( ( self->container->flags
628  {
629  check(CS_ERROR_INVALID_ARGUMENT);
630  }
631  if( self->state == adapter_t::EMPTY
632  || self->state == adapter_t::SINGLETON )
633  {
634  check(CS_ERROR_INVALID_ARGUMENT);
635  }
636  self->at_end();
637  return &self->inner->counters;
638  }
639  protected:
640  iterator_adapter_mixin(){}
641  public:
662  size_t get_scanned_count() const
663  { return get_counters()->scanned; }
664 
665 
687  size_t get_unscanned_count() const
688  { return get_counters()->unscanned; }
689 
690 
709  size_t get_matched_count() const
710  { return get_counters()->matched; }
711  };
712 
714  class xr_intra_definition_iterator_policy_container{
715  xr_intra_definition_iterator_policy_container();
716  public:
717  sfile file;
718  line_number line_lb, line_ub;
719  xr_intra_definition_iterator_policy_container(
720  sfile _file,
721  line_number _line_lb,
722  line_number _line_ub)
723  : file(_file)
724  , line_lb(_line_lb)
725  , line_ub(_line_ub){}
726  };
727 
728  class xr_intra_definition_iterator_policy{
729  public:
730  typedef cs_xref_intra_def_iter iterator_impl;
731  typedef xr_tuple key;
732  typedef xr_intra_definition_iterator_policy_container ctype;
733 
734  static cs_result iter_first(
735  const ctype &container,
736  cglue<key>::ctype *val,
737  iterator_impl *it)
738  {
739  return cs_xref_intra_def_iter_first(
740  cglue<sfile>::unwrap(container.file),
741  container.line_lb,
742  container.line_ub,
743  val, it );
744  }
745  static cs_result iter_next(
746  const ctype &container,
747  cglue<key>::ctype *val,
748  iterator_impl *it)
749  { return cs_xref_intra_def_iter_next( val, it ); }
750  static cs_result iter_close(iterator_impl *it)
751  { return cs_xref_intra_def_iter_close( it ); }
752  static const char *name()
753  { return "xr_intra_definition_iterator"; }
754  };
755 
756 
757 
759 
796  class xr_file_query{
797  friend class xr_query_iterator_policy_container;
798  std::vector<std::string> absolutes;
799  std::vector<std::string> absolutes_ss;
800  std::vector<std::string> dirnames;
801  std::vector<std::string> dirnames_ss;
802  std::vector<std::string> basenames;
803  std::vector<std::string> basenames_ss;
804  std::vector<sfile> sfs;
805  std::vector<line_number> lines;
806  bool reject_libmodels;
807  public:
824  void add_absolute_filter(const std::string &s)
825  { absolutes.push_back(s); }
826 
827 
844  void add_absolute_substring_filter(const std::string &s)
845  { absolutes_ss.push_back(s); }
846 
847 
864  void add_dirname_filter(const std::string &s)
865  { dirnames.push_back(s); }
866 
867 
885  void add_dirname_substring_filter(const std::string &s)
886  { dirnames_ss.push_back(s); }
887 
888 
903  void add_basename_filter(const std::string &s)
904  { basenames.push_back(s); }
905 
906 
922  void add_basename_substring_filter(const std::string &s)
923  { basenames_ss.push_back(s); }
924 
925 
936  void add_file_filter(const sfile &s)
937  { sfs.push_back(s); }
938 
939 
951  { lines.push_back(s); }
952 
953 
962  void set_reject_libmodels(bool s)
963  { reject_libmodels = s; }
964  xr_file_query()
965  : reject_libmodels(false){}
966 
968  std::string as_repr() const
969  { return CS_AS_REPR(xr_file_query, std::string("...")); }
970 
972  std::string as_string() const
973  { return as_repr(); }
974  };
975 
983  inline std::ostream &operator<<( std::ostream &out,
984  const xr_file_query &a )
985  { return out << a.as_repr(); }
986 
987 
988 #ifdef SWIG
989 #if defined(SWIGPYTHON)
990  %rename(_xr_tuple_comparator) xr_tuple_comparator;
991 #endif
992 #if defined(SWIGCSHARP)
993  %rename(_xr_tuple_comparator_csharp) xr_tuple_comparator;
994  %typemap(csclassmodifiers) xr_tuple_comparator "public abstract class";
995 #endif
996 #else
997 
998  struct xr_tuple_comparator_swig_exc{};
1000 /* The following is important to avoid multiply defined symbols, which
1001  * swig will otherwise cause. it is hackish, but effective.
1002  */
1003 #if defined(SWIGCSHARP)
1004 #define SwigDirector_xr_tuple_comparator CSharp_SwigDirector_xr_tuple_comparator
1005 #elif defined(SWIGJAVA)
1006 #define SwigDirector_xr_tuple_comparator Java_SwigDirector_xr_tuple_comparator
1007 #endif
1008 #endif
1009 
1010 
1029  class xr_tuple_comparator{
1030  public:
1031 #if defined(SWIG) && defined(SWIGJAVA)
1032  %rename(cmp) operator();
1033 #endif
1034 #if defined(SWIG) && defined(SWIGCSHARP)
1035  %rename(_cmp) operator();
1036 #endif
1037 #if defined(SWIG) && defined(SWIGJAVA)
1038  %javaexception("java.lang.Exception") operator() {
1039  $action
1040  }
1041 #endif
1042 
1043 
1058  virtual int operator()(const xr_tuple &a, const xr_tuple &b) = 0;
1060  virtual ~xr_tuple_comparator(){}
1061  };
1062 #if defined(SWIG) && defined(SWIGPYTHON)
1063  %pythoncode{
1064  class _xr_tuple_comparator2(_xr_tuple_comparator):
1065  def __init__(self, func):
1066  _xr_tuple_comparator.__init__(self)
1067  self.func = func
1068  def __call__(self, a, b): return self.func(a, b)
1069  }
1070 #endif
1071 
1072 
1148  class xr_query{
1149  friend class xr_query_iterator_policy_container;
1150  size_t offset;
1151  size_t limit;
1152  std::vector<xr_kind> kinds;
1153  std::vector<xr_role> roles;
1154  std::vector<xr_kind_role> kind_roles;
1155  std::vector<csuint64> term_hashes;
1156  xr_file_query occurrence;
1157  xr_file_query definition;
1159  xr_tuple_comparator *cmp;
1160 
1161  public:
1172  void add_kind_filter(xr_kind s)
1173  { kinds.push_back(s); }
1174 
1175 
1186  void add_role_filter(xr_role s)
1187  { roles.push_back(s); }
1188 
1189 
1200  void add_kind_role_filter(xr_kind_role s)
1201  { kind_roles.push_back(s); }
1202 
1203 
1226  void add_term_filter(const std::string &s)
1227  { term_hashes.push_back(xr_namehash(s)); }
1228 
1229 
1249  void add_term_filter(const csuint64 s)
1250  {
1251  if( s != 0 && s + 1 != 0 )
1252  term_hashes.push_back(s);
1253  }
1254 
1255 
1267  void set_occurrence_filter(const xr_file_query &s)
1268  { occurrence = s; }
1269 
1270 
1282  void set_definition_filter(const xr_file_query &s)
1283  { definition = s; }
1284 
1285 
1295  void set_offset(size_t s)
1296  { offset = s; }
1297 
1298 
1312  void set_limit(size_t s)
1313  { limit = s; }
1314 
1315 
1322  void set_flags(xr_query_flags s)
1323  { flags = s; }
1324 
1325 #if defined(SWIG) && defined(SWIGPYTHON)
1326  %feature("shadow") set_cmp %{
1327  def set_cmp(self, val):
1328  if not callable(val):
1329  return $action(self, val)
1330  return $action(self, _xr_tuple_comparator2(val))%}
1331 #endif
1333 #if defined(SWIG) && defined(SWIGJAVA)
1334 #endif
1335 
1336 /* I haven't yet been able to figure out a sane way to make this work
1337  * for C# when the callback has an uncaught exception. Sorry.
1338  */
1339 #if 0 && defined(SWIG) && defined(SWIGCSHARP)
1340  %typemap(cscode) project %{
1341  public xr_query_iterator token_search(xr_query q) {
1342  q.clear_exception();
1343  xr_query_iterator rv = _token_search(q);
1344  q.check_exception();
1345  return rv;
1346  }
1347  %}
1348 #endif
1349 
1350 #if !defined(SWIG) || !defined(SWIGCSHARP)
1351 
1352  /* This DISOWN business sucks because it means _cmp leaks for
1353  * certain when using the higher level SWIG bindings (python,
1354  * java, c#). It would be nice if we could essentially
1355  * increment a refcount on the object from the higher level
1356  * language and decrement it when we are done, but I don't
1357  * think I've seen a facility for doing this in SWIG.
1358  */
1359  DISOWN_PARAMETER(xr_tuple_comparator *_cmp);
1360 
1361 
1397  void set_cmp(xr_tuple_comparator *_cmp)
1398  { cmp = _cmp; }
1399 #endif
1400 
1410  xr_query() : offset(0), limit(0)
1411  , flags(xr_query_flags::NONE)
1412  , cmp(NULL){}
1413 
1415  std::string as_repr() const
1416  { return CS_AS_REPR(xr_query, std::string("...")); }
1417 
1419  std::string as_string() const
1420  { return as_repr(); }
1421  };
1422 
1429  inline std::ostream &operator<<( std::ostream &out,
1430  const xr_query &a )
1431  { return out << a.as_repr(); }
1432 
1433  class xr_query_iterator_policy_container{
1434  xr_query_iterator_policy_container();
1435 
1436  template <typename T>
1437  static typename cglue<T>::ctype *make_c_array(
1438  const std::vector<T> &v, typename cglue<T>::ctype term)
1439  {
1440  typedef typename cglue<T>::ctype CT;
1441  CT *rv;
1442  if( v.size() == 0 )
1443  return NULL;
1444  rv = new CT[v.size()+1];
1445  for(size_t i = 0; i < v.size(); i++)
1446  rv[i] = cglue<T>::unwrap(v[i]);
1447  rv[v.size()] = term;
1448  return rv;
1449  }
1450 
1451  template <typename T>
1452  static void delete_c_array(T v)
1453  {
1454  if( v )
1455  delete[] v;
1456  }
1457 
1458  template <typename T>
1459  static T *copy_c_array(const T *v, T term)
1460  {
1461  size_t i;
1462  T *rv;
1463  if( !v )
1464  return NULL;
1465  for( i = 0; memcmp(&v[i],&term,sizeof(term)); i++ );
1466  rv = new T[i+1];
1467  for( i = 0; memcmp(&v[i],&term,sizeof(term)); i++ )
1468  rv[i] = v[i];
1469  rv[i] = term;
1470  return rv;
1471  }
1472 
1473  static char **make_c_str_vector(const std::vector<std::string> &v)
1474  {
1475  if( v.size() == 0 )
1476  return NULL;
1477  char **rv = new char*[v.size() + 1];
1478  for(size_t i = 0; i < v.size(); i++)
1479  {
1480  char *p = new char[v[i].size()+1];
1481  memcpy( p, v[i].c_str(), v[i].size() );
1482  p[v[i].size()] = 0;
1483  rv[i] = p;
1484  }
1485  rv[v.size()] = NULL;
1486  return rv;
1487  }
1488 
1489  static void delete_c_str_vector(char **v)
1490  {
1491  if( v )
1492  {
1493  for( size_t i = 0; v[i]; i++ )
1494  delete[] v[i];
1495  delete[] v;
1496  }
1497  }
1498 
1499  static char **copy_c_str_vector(const char *const *v)
1500  {
1501  if( !v )
1502  return NULL;
1503  size_t i;
1504  for( i = 0; v[i]; i++ );
1505  char **rv = new char *[i+1];
1506  for( i = 0; v[i]; i++ )
1507  {
1508  const char *p = v[i];
1509  size_t len = strlen(p);
1510  char *q = new char[len + 1];
1511  memcpy(q, p, len+1);
1512  rv[i] = q;
1513  }
1514  rv[i] = NULL;
1515  return rv;
1516  }
1517 
1518  static void make_file_query(const xr_file_query q,
1519  cs_xref_file_query &out)
1520  {
1521  out.absolutes = make_c_str_vector(q.absolutes);
1522  out.absolutes_ss = make_c_str_vector(q.absolutes_ss);
1523  out.dirnames = make_c_str_vector(q.dirnames);
1524  out.dirnames_ss = make_c_str_vector(q.dirnames_ss);
1525  out.basenames = make_c_str_vector(q.basenames);
1526  out.basenames_ss = make_c_str_vector(q.basenames_ss);
1527  out.sfs = make_c_array(q.sfs, CS_SF_NULL);
1528  out.lines = make_c_array(q.lines, 0);
1529  out.reject_libmodels = q.reject_libmodels;
1530  }
1531 
1532  static void delete_file_query(cs_xref_file_query &q)
1533  {
1534  delete_c_str_vector(q.absolutes);
1535  delete_c_str_vector(q.absolutes_ss);
1536  delete_c_str_vector(q.dirnames);
1537  delete_c_str_vector(q.dirnames_ss);
1538  delete_c_str_vector(q.basenames);
1539  delete_c_str_vector(q.basenames_ss);
1540  delete_c_array(q.sfs);
1541  delete_c_array(q.lines);
1542  }
1543 
1544  static void copy_file_query(const cs_xref_file_query &q,
1545  cs_xref_file_query &out)
1546  {
1547  out.absolutes = copy_c_str_vector(q.absolutes);
1548  out.absolutes_ss = copy_c_str_vector(q.absolutes_ss);
1549  out.dirnames = copy_c_str_vector(q.dirnames);
1550  out.dirnames_ss = copy_c_str_vector(q.dirnames_ss);
1551  out.basenames = copy_c_str_vector(q.basenames);
1552  out.basenames_ss = copy_c_str_vector(q.basenames_ss);
1553  out.sfs = copy_c_array(q.sfs, CS_SF_NULL);
1554  out.lines = copy_c_array(q.lines, (cs_line)0);
1555  out.reject_libmodels = q.reject_libmodels;
1556  }
1557 
1558  static int delegate_to_cmp(const cs_xref_tuple *a,
1559  const cs_xref_tuple *b,
1560  void *_ctx)
1561  {
1562  xr_query_iterator_policy_container *ctr =
1563  static_cast<xr_query_iterator_policy_container*>(_ctx);
1564  /* This function is called by C code, which isn't going to
1565  * unwind in reaction to a c++ exception properly.
1566  * Unfortunately, this means we need to catch any exceptions
1567  * here and now, and then re-raise them when everything
1568  * finishes.
1569  *
1570  * Unfortunately, this means we need to know about every type
1571  * of exception that could show up here.
1572  */
1573  if( ctr->m_res == result::SUCCESS )
1574  {
1575 #if !CS_CPP_NO_EXCEPTIONS
1576  try{
1577 #endif
1578  return (*ctr->m_cmp)(cglue<xr_tuple>::wrap(*a),
1579  cglue<xr_tuple>::wrap(*b));
1580 #if! CS_CPP_NO_EXCEPTIONS
1581  } catch(result &r) {
1582  ctr->m_res = r;
1583 #if defined(SWIG_BUILD)
1584  } catch(Swig::DirectorException &) {
1585  ctr->m_res = result::ERROR_FOREIGN_EXCEPTION;
1586 #endif
1587  } catch(...) {
1588  ctr->m_res = result::INTERNAL_ERROR_UNKNOWN;
1589  }
1590 #endif
1591  }
1592  return 0;
1593  }
1594 
1595  public:
1596  xr_tuple_comparator *m_cmp;
1597  result m_res;
1598  cs_xref_query inner;
1599 
1600  xr_query_iterator_policy_container(const xr_query &q)
1601  : m_cmp(q.cmp)
1602  , m_res(result::SUCCESS)
1603  {
1604  memset( &inner, 0, sizeof(inner) );
1605  inner.offset = q.offset;
1606  inner.limit = q.limit;
1607  inner.kinds = make_c_array(q.kinds, csxrk_count);
1608  inner.roles = make_c_array(q.roles, csxrr_count);
1609  inner.kind_roles = make_c_array(q.kind_roles, csxrkr_count);
1610  inner.term_hashes = make_c_array(q.term_hashes, static_cast<csuint64>(0));
1611  make_file_query(q.occurrence, inner.occurrence);
1612  make_file_query(q.definition, inner.definition);
1613  inner.flags = cglue<xr_query_flags>::unwrap(q.flags);
1614  if( m_cmp )
1615  {
1616  inner.cmp = delegate_to_cmp;
1617  inner.ctx = this;
1618  }
1619  }
1620 
1621  ~xr_query_iterator_policy_container()
1622  {
1623  delete_c_array(inner.kinds);
1624  delete_c_array(inner.roles);
1625  delete_c_array(inner.kind_roles);
1626  delete_c_array(inner.term_hashes);
1627  delete_file_query(inner.occurrence);
1628  delete_file_query(inner.definition);
1629  }
1630 
1631  xr_query_iterator_policy_container(
1632  const xr_query_iterator_policy_container &q)
1633  : m_cmp(q.m_cmp)
1634  , m_res(q.m_res)
1635  {
1636  inner = q.inner;
1637  inner.kinds = copy_c_array(q.inner.kinds, csxrk_count);
1638  inner.roles = copy_c_array(q.inner.roles, csxrr_count);
1639  inner.kind_roles = copy_c_array(q.inner.kind_roles, csxrkr_count);
1640  inner.term_hashes = copy_c_array(q.inner.term_hashes, static_cast<csuint64>(0));
1641  copy_file_query(q.inner.occurrence, inner.occurrence);
1642  copy_file_query(q.inner.definition, inner.definition);
1643  inner.flags = q.inner.flags;
1644  if( m_cmp )
1645  {
1646  inner.cmp = delegate_to_cmp;
1647  inner.ctx = this;
1648  }
1649  else
1650  {
1651  inner.cmp = NULL;
1652  inner.ctx = NULL;
1653  }
1654  }
1655  };
1656 
1657  class xr_query_iterator_policy{
1658  xr_query_iterator_policy();
1659  public:
1660  typedef cs_xref_query_iter iterator_impl;
1661  typedef xr_tuple key;
1662  typedef xr_query_iterator_policy_container ctype;
1663 
1664  static cs_result iter_first(
1665  const ctype &container,
1666  cglue<key>::ctype *val,
1667  iterator_impl *it)
1668  {
1669  cs_result r = cs_xref_query_iter_first(
1670  &container.inner,
1671  val, it );
1672 #if !CS_CPP_NO_EXCEPTIONS
1673  if( container.m_res == result::ERROR_FOREIGN_EXCEPTION )
1674  /* This exception has to have a distinct type from
1675  * result so that the wrong catch doesn't catch it. */
1676  throw xr_tuple_comparator_swig_exc();
1677 #endif
1678  container.m_res.check();
1679  return r;
1680  }
1681  static cs_result iter_next(
1682  const ctype &container,
1683  cglue<key>::ctype *val,
1684  iterator_impl *it)
1685  {
1686  cs_result r = cs_xref_query_iter_next( val, it );
1687 #if !CS_CPP_NO_EXCEPTIONS
1688  if( container.m_res == result::ERROR_FOREIGN_EXCEPTION )
1689  /* This exception has to have a distinct type from
1690  * result so that the wrong catch doesn't catch it. */
1691  throw xr_tuple_comparator_swig_exc();
1692 #endif
1693  container.m_res.check();
1694  return r;
1695  }
1696  static cs_result iter_close(iterator_impl *it)
1697  { return cs_xref_query_iter_close( it ); }
1698  static const char *name()
1699  { return "xr_query_iterator"; }
1700  };
1701 #endif
1702  template<>
1703  class iterator_adapter_mixin<xr_query_iterator_policy>
1704  {
1705  typedef iterator_adapter<xr_query_iterator_policy> adapter_t;
1706  const cs_xref_result_counters *get_counters() const
1707  {
1708  const adapter_t *self = static_cast<const adapter_t*>(this);
1709  if( !( self->container->inner.flags & csxrqf_populate_counters ) )
1710  {
1711  check(CS_ERROR_INVALID_ARGUMENT);
1712  }
1713  if( self->state == adapter_t::EMPTY
1714  || self->state == adapter_t::SINGLETON )
1715  {
1716  check(CS_ERROR_INVALID_ARGUMENT);
1717  }
1718  self->at_end();
1719  return &self->inner->counters;
1720  }
1721  protected:
1722  iterator_adapter_mixin(){}
1723  public:
1742  size_t get_scanned_count() const
1743  { return get_counters()->scanned; }
1744 
1745 
1763  size_t get_unscanned_count() const
1764  { return get_counters()->unscanned; }
1765 
1766 
1782  size_t get_matched_count() const
1783  { return get_counters()->matched; }
1784  };
1785 
1787 
1788 }
1789 
1790 #if defined(SWIG) && defined(SWIGPYTHON)
1791 %exception cs::iterator_adapter<cs::xr_query_iterator_policy>::__next__{
1792  try { $action }
1793  catch (cs::xr_tuple_comparator_swig_exc &) {
1794  SWIG_fail;
1795  }
1796 }
1797 %exception cs::iterator_adapter<cs::xr_query_iterator_policy>::at_end{
1798  try { $action }
1799  catch (cs::xr_tuple_comparator_swig_exc &) {
1800  SWIG_fail;
1801  }
1802 }
1803 #endif
1804 
1805 
1806 #endif /* CS_XREF_HPP */
xr_tuple(csuint64 _namehash, xr_kind_role _kr, bool _complete, sfile _file, line_number _line, sfile _def_file, line_number _def_line)
Constructor.
Definition: cs_xref.hpp:160
void add_file_filter(const sfile &s)
Add a file filter to a xr_file_query object.
Definition: cs_xref.hpp:941
cs_line line_number
A line number in a source file (sfile) or source file instance (sfileinst).
Definition: cs_types.hpp:387
static const xr_occ_iter_flags POPULATE_COUNTERS
Compute and store tuple counts for later retrieval by xr_occurrence_iterator or xr_homonym_iterator g...
Definition: cs_xref_fwd.hpp:127
Namespace for CodeSonar/CodeSurfer API.
Definition: cs_ast.hpp:33
Flag class: additional properties for an xr_query.
Definition: cs_xref_fwd.hpp:146
csuint64 xr_namehash(const std::string &s)
Hash a token name.
Definition: cs_xr_kind_role.hpp:20
int cmp(const xr_kind_role &other) const
Comparison function for xr_kind_role, with respect to a stable overall ordering.
Definition: cs_xr_kind_role.hpp:70
Describes an occurrence of a token in a particular kind-role and the definition corresponding to that...
Definition: cs_xref.hpp:35
cs_hash_t hash() const
Hash function for xr_tuple.
Definition: cs_xref.hpp:225
csuint64 get_namehash() const
Get a hash of the token name.
Definition: cs_xref.hpp:63
A CodeSonar or CodeSurfer project.
Definition: cs_project.hpp:392
cs::xr_occurrence_iterator_policy
Definition: cs_xref.hpp:406
cs::xr_query_iterator_policy
Definition: cs_xref.hpp:1672
static const xr_occ_iter_flags NONE
Empty set: contains no flags.
Definition: cs_xref_fwd.hpp:82
int cmp(const sfile &other) const
Comparison function for sfile.
Definition: cs_sfile_decl.hpp:104
cs::xr_intra_definition_iterator_policy
Definition: cs_xref.hpp:733
static const result SUCCESS
The function was successful.
Definition: cs_result.hpp:22
sfile get_def_file() const
Get the source file containing the token&#39;s definition.
Definition: cs_xref.hpp:107
Abstract base class for xref_tuple comparators: functors that specify an ordering on the results (xr_...
Definition: cs_xref.hpp:1039
static const result SUCCESS
The function was successful.
Definition: cs_result_decls.hpp:21
line_number get_def_line() const
Get the source file line containing the token definition.
Definition: cs_xref.hpp:115
bool get_complete() const
Check: is the definition complete?
Definition: cs_xref.hpp:80
cs::xr_homonym_iterator_policy
Definition: cs_xref.hpp:571
void add_absolute_substring_filter(const std::string &s)
Add an absolute path substring filter to a xr_file_query object.
Definition: cs_xref.hpp:849
std::string as_repr() const
Get a representation of a xr_tuple object that includes information useful for debugging.
Definition: cs_xref.hpp:180
std::string as_string() const
Get a simple string representation of a xr_tuple object.
Definition: cs_xref.hpp:266
Flag class: properties for xr_occurrence_iterator and xr_homonym_iterator iterators.
Definition: cs_xref_fwd.hpp:70
cs::iterator_adapter_mixin
Iterator class template.
Definition: cs_iterator_adapter.hpp:35
cs_hash_t hash() const
Get a hash value for a sfile.
Definition: cs_sfile_decl.hpp:104
std::string as_string() const
Get a simple string representation of a xr_file_query object.
Definition: cs_xref.hpp:982
Iterator over the results (xr_tuple) of an xr_query.
Definition: cs_tplt_instantiations.hpp:1281
void set_reject_libmodels(bool s)
Specify whether or not the query should include library model files.
Definition: cs_xref.hpp:967
static const point_syntax_element NONE
All other program points.
Definition: cs_point_syntax_element_decls.hpp:21
cs_hash_t hash() const
Hash function for xr_kind_role.
Definition: cs_xr_kind_role.hpp:70
virtual ~xr_tuple_comparator()
Destructor.
Definition: cs_xref.hpp:1070
void add_absolute_filter(const std::string &s)
Add an absolute path filter to a xr_file_query object.
Definition: cs_xref.hpp:829
std::string get_name() const
Get the source token corresponding to an xr_tuple.
Definition: cs_xref.hpp:279
std::string as_repr() const
Get a representation of a xr_file_query object that includes information useful for debugging...
Definition: cs_xref.hpp:976
A source file.
Definition: cs_sfile_decl.hpp:98
A collection of filters used to restrict a xr_query.
Definition: cs_xref.hpp:801
void add_dirname_filter(const std::string &s)
Add a dirname path filter to a xr_file_query object.
Definition: cs_xref.hpp:869
void add_basename_filter(const std::string &s)
Add a basename filter to a xr_file_query object.
Definition: cs_xref.hpp:908
Fully specifies a cross-referencing query over the tokens in an analyzed project. ...
Definition: cs_xref.hpp:1158
void add_dirname_substring_filter(const std::string &s)
Add a dirname path substring filter to a xr_file_query object.
Definition: cs_xref.hpp:890
Enumeration class: describes the kind of a (non-keyword) token.
Definition: cs_xr_kind_role.hpp:31
cs::xr_definition_iterator_policy
Definition: cs_xref.hpp:352
cs::iterator_adapter
Iterator class template.
Definition: cs_iterator_adapter.hpp:65
void add_line_number_filter(line_number s)
Add a line number filter to a xr_file_query object.
Definition: cs_xref.hpp:955
Enumeration class: describes the role that a token is playing at a particular occurrence of that toke...
Definition: cs_xr_kind_role.hpp:48
static const result ERROR_FOREIGN_EXCEPTION
An exception occured in a non-native language.
Definition: cs_result.hpp:572
int cmp(const xr_tuple &other) const
Comparison function for xr_tuple, with respect to a stable overall ordering.
Definition: cs_xref.hpp:193
virtual int operator()(const xr_tuple &a, const xr_tuple &b)=0
Comparison function for xr_tuple.
Enumeration class: describes a valid token kind-role (kind-usage) pair.
Definition: cs_xr_kind_role.hpp:67
line_number get_line() const
Get the source file line containing the token occurrence.
Definition: cs_xref.hpp:96
xr_kind_role get_kind_role() const
Get the token&#39;s kind-role.
Definition: cs_xref.hpp:71
void add_basename_substring_filter(const std::string &s)
Add a basename substring filter to a xr_file_query object.
Definition: cs_xref.hpp:927
static const result INTERNAL_ERROR_UNKNOWN
This error should never be seen by an API client, even when something is horribly wrong...
Definition: cs_result.hpp:1180
sfile get_file() const
Get the source file containing the token occurrence.
Definition: cs_xref.hpp:88