1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the class library                   */
4    	/*       SoPlex --- the Sequential object-oriented simPlex.                  */
5    	/*                                                                           */
6    	/*    Copyright (C) 1996-2022 Konrad-Zuse-Zentrum                            */
7    	/*                            fuer Informationstechnik Berlin                */
8    	/*                                                                           */
9    	/*  SoPlex is distributed under the terms of the ZIB Academic Licence.       */
10   	/*                                                                           */
11   	/*  You should have received a copy of the ZIB Academic License              */
12   	/*  along with SoPlex; see the file COPYING. If not email to soplex@zib.de.  */
13   	/*                                                                           */
14   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15   	
16   	/**@file  nameset.h
17   	 * @brief Set of strings.
18   	 */
19   	#ifndef _NAMESET_H_
20   	#define _NAMESET_H_
21   	
22   	#include <assert.h>
23   	
24   	#include "soplex/spxdefines.h"
25   	#include "soplex/dataset.h"
26   	#include "soplex/datahashtable.h"
27   	#include "soplex/datakey.h"
28   	
29   	namespace soplex
30   	{
31   	/**@class NameSet
32   	   @brief   Set of strings.
33   	   @ingroup Elementary
34   	
35   	   Class NameSet implements a symbol or name table. It allows to store or
36   	   remove names (i.e., \c char*), but does not provide means for manipulating
37   	   stored names.
38   	
39   	   Names in a NameSet may be accessed via numbers from 0 through num()-1
40   	   and via \ref soplex::DataKey "DataKeys". See DataSet for a description of
41   	   these concepts.
42   	
43   	   At a time a NameSet can hold a maximum of max() entries. This can be
44   	   reset with method reMax(). If more than max() names are added to a
45   	   NameSet, it adjusts itself automatically to the required size.  This
46   	   implies, that references to names within a NameSet may become invalid if
47   	   the NameSet is expanded.
48   	
49   	   All names (i.e., the actual char strings) in a NameSet are stored in one
50   	   continuous memory block of size memMax(). At one time memSize() bytes of
51   	   it are used for actually saving names; the remaining memory is free to hold
52   	   additional names. memRemax() can be used to reset memMax() but not lower
53   	   than to memSize(). Method memPack() performs a garbage collection to
54   	   gain free memory resulting from removed names.
55   	
56   	   @warning Since the keys the NameSet uses to reference the strings are
57   	            generated internally, it is extremly important that the calls
58   	            to DataSet from within NameSet are synchronous to any calls
59   	            outside to DataSet, such as in row or column adding.
60   	*/
61   	class NameSet
62   	{
63   	public:
64   	
65   	   /**@brief   Handles of names in a NameSet.
66   	    * @ingroup Elementary
67   	    *
68   	    *  Class Name provides the handles (i.e., char*s) of names in a
69   	    *  NameSet.
70   	    */
71   	   class Name
72   	   {
73   	   private:
74   	
75   	      //------------------------------
76   	      /**@name Private Data */
77   	      ///@{
78   	      static const char deflt;     ///< default zero string.
79   	      ///@}
80   	
81   	   public:
82   	
83   	      //------------------------------
84   	      /**@name Public Data */
85   	      ///@{
86   	      const char* name;      ///< pointer to the name string.
87   	      ///@}
88   	
89   	      //------------------------------
90   	      /**@name Friends */
91   	      ///@{
92   	      /// equality operator.
93   	      friend int operator==(const Name& n1, const Name& n2)
94   	      {
95   	         return (strcmp(n1.name, n2.name) == 0);
96   	      }
97   	      /// output operator.
98   	      friend std::ostream& operator<<(std::ostream& out, const Name& n)
99   	      {
100  	         return out << n.name;
101  	      }
102  	      ///@}
103  	
104  	      //------------------------------
105  	      /**@name Debugging */
106  	      ///@{
107  	      /// consistency check.
108  	      bool isConsistent() const
109  	      {
110  	         return (name != 0);
111  	      }
112  	      ///@}
113  	
114  	      //------------------------------------
115  	      /**@name Constructors / destructors */
116  	      ///@{
117  	      /// default constructor.
118  	      Name()
119  	         : name(&deflt)
120  	      {}
121  	      /// copy constructor.
122  	      /** Only the pointer to the name is copied, but not the name itself.
123  	       */
124  	      Name(const Name& str)
125  	         : name(str.name)
126  	      {}
127  	      /// implictly constructs a Name out of a C style character string.
128  	      Name(const char* str)
129  	         : name(str)
130  	      {}
131  	
132  	      Name& operator=(const Name& old)
133  	      {
(1) Event self_assign: No protection against the object assigning to itself.
134  	         name = old.name;
135  	         return *this;
136  	      }
137  	      ///@}
138  	   };
139  	
140  	private:
141  	
142  	   //------------------------------
143  	   /**@name Data */
144  	   ///@{
145  	   DataSet < int > set;  ///< name set.
146  	   char* mem;            ///< string memory
147  	   int memmax;           ///< size of string memory
148  	   int memused;          ///< size of used string memory
149  	   /** Every name in a NameSet is assigned a DataKey by which it can be
150  	       accessed (see NameSet::operator[]()). See DataKey for a more
151  	       detailed description of the concept of Keys.
152  	   */
153  	   DataHashTable < Name, DataKey > hashtab;  ///< hashtable for names
154  	   ///@}
155  	
156  	public:
157  	
158  	   //------------------------------
159  	   /**@name Inquiry */
160  	   ///@{
161  	   /// returns \p num 'th name of NameSet.
162  	   const char* operator[](int pnum) const
163  	   {
164  	      return &mem[set[pnum]];
165  	   }
166  	
167  	   /// returns name for DataKey \p pkey of NameSet.
168  	   const char* operator[](const DataKey& pkey) const
169  	   {
170  	      return &mem[set[pkey]];
171  	   }
172  	
173  	   /// returns nr. of names in NameSet.
174  	   int num() const
175  	   {
176  	      return set.num();
177  	   }
178  	
179  	   /// returns maximum nr. of names that fit into NameSet.
180  	   int max() const
181  	   {
182  	      return set.max();
183  	   }
184  	
185  	   /// returns maximum DataKey::idx used in NameSet.
186  	   int size() const
187  	   {
188  	      return set.size();
189  	   }
190  	
191  	   /// returns maximum length of string memory.
192  	   int memMax() const
193  	   {
194  	      return memmax;
195  	   }
196  	
197  	   /// returns used length of string memory.
198  	   int memSize() const
199  	   {
200  	      return memused;
201  	   }
202  	
203  	   /// returns DataKey of the \p pnum 'th name in NameSet.
204  	   DataKey key(int pnum) const
205  	   {
206  	      return set.key(pnum);
207  	   }
208  	
209  	   /// returns DataKey of name \p str in NameSet.
210  	   DataKey key(const char* str) const
211  	   {
212  	      const Name nam(str);
213  	      const DataKey* result = hashtab.get(nam);
214  	      return result == 0 ? DataKey() : *hashtab.get(nam);
215  	   }
216  	
217  	   /// returns number of name with DataKey \p pkey in NameSet.
218  	   int number(const DataKey& pkey) const
219  	   {
220  	      return set.number(pkey);
221  	   }
222  	
223  	   /// returns number of name \p str in NameSet.
224  	   int number(const char* str) const
225  	   {
226  	      const Name nam(str);
227  	
228  	      if(hashtab.has(nam))
229  	      {
230  	         assert(hashtab.get(nam) != 0);
231  	         return number(*hashtab.get(nam));
232  	      }
233  	      else
234  	         return -1;
235  	   }
236  	
237  	   /// does NameSet has a name with number \p pnum?
238  	   bool has(int pnum) const
239  	   {
240  	      return set.has(pnum);
241  	   }
242  	
243  	   /// does NameSet has a name \p str?
244  	   bool has(const char* str) const
245  	   {
246  	      const Name nam(str);
247  	      return hashtab.has(nam);
248  	   }
249  	
250  	   /// does NameSet has a name with DataKey \p pkey?
251  	   bool has(const DataKey& pkey) const
252  	   {
253  	      return set.has(pkey);
254  	   }
255  	   ///@}
256  	
257  	   //----------------------------
258  	   /**@name Extension */
259  	   ///@{
260  	   ///
261  	   void add(const char* str);
262  	   /// adds name \p str to NameSet.
263  	   void add(DataKey& key, const char* str);
264  	
265  	   ///
266  	   void add(const NameSet& set);
267  	   /// adds all names in \p set to NameSet.
268  	   void add(DataKey key[], const NameSet& nset);
269  	   ///@}
270  	
271  	
272  	   //----------------------------
273  	   /**@name Shrinking */
274  	   ///@{
275  	   /// removes name with DataKey \p key from NameSet.
276  	   void remove(const DataKey& key);
277  	
278  	   /// removes \p pnum 'th name from NameSet.
279  	   void remove(int pnum)
280  	   {
281  	      remove(key(pnum));
282  	   }
283  	
284  	   /// removes name \p str from NameSet.
285  	   void remove(const char* str);
286  	
287  	   /// removes \p n names with DataKeys \p keys from NameSet.
288  	   void remove(const DataKey keys[], int n);
289  	
290  	   /// removes \p n names with numbers \p nums from NameSet.
291  	   void remove(const int nums[], int n);
292  	
293  	   /// remove all entries where \p dstat is less than zero.
294  	   void remove(int dstat[]);
295  	
296  	   /// removes all names from NameSet.
297  	   void clear();
298  	   ///@}
299  	
300  	
301  	   //----------------------------
302  	   /**@name Memory Control */
303  	   ///@{
304  	   /// resets max() to \p newmax.
305  	   void reMax(int newmax = 0);
306  	
307  	   /// resets memMax() to \p newmax.
308  	   void memRemax(int newmax = 0);
309  	
310  	   /// garbage collection.
311  	   void memPack();
312  	   ///@}
313  	
314  	
315  	   //----------------------------
316  	   /**@name Control Parameters */
317  	   ///@{
318  	   /// memory extension factor for entries.
319  	   /** When more than max() names are added to a NameSet, it is
320  	       automatically resized to fit the additional names. Parameter
321  	       \p factor is the factor by which the element memory is extended to do
322  	       so.
323  	    */
324  	   Real factor;
325  	
326  	   /// memory extension factor for names.
327  	   /** When the names added to a NameSet do no longer fit into the name
328  	       memory (i.e. the memory for saving the strings), it is automatically
329  	       resized to fit the additional names. Parameter \p memFactor is the
330  	       factor by which this memory is extended to do so.
331  	    */
332  	   Real memFactor;
333  	   ///@}
334  	
335  	   //----------------------------
336  	   /**@name Miscellaneous */
337  	   ///@{
338  	   /// consistency check.
339  	   bool isConsistent() const;
340  	   ///@}
341  	
342  	   //--------------------------------------
343  	   /**@name Constructors / Destructors */
344  	   ///@{
345  	   /// default constructor.
346  	   /** @param      max     start value for max()
347  	    *  @param      mmax    start value for memMax()
348  	    *  @param      fac     start value for #factor
349  	    *  @param      memFac  start value for #memFactor
350  	    */
351  	   explicit
352  	   NameSet(int max = 10000,
353  	           int mmax = -1,
354  	           Real fac = 2,
355  	           Real memFac = 2);
356  	
357  	   /// destructor.
358  	   ~NameSet();
359  	   ///@}
360  	
361  	private:
362  	
363  	   //--------------------------------------
364  	   /**@name Blocked */
365  	   ///@{
366  	   /// copy constructor.
367  	   NameSet(const NameSet& old);
368  	
369  	   /// assignment operator.
370  	   NameSet& operator=(const NameSet& rhs);
371  	   ///@}
372  	};
373  	
374  	extern std::ostream& operator<<(std::ostream& s, const NameSet& nset);
375  	
376  	} // namespace soplex
377  	#endif // _NAMESET_H_
378