HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_PackageUtils.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_PackageUtils.h
7  *
8  * COMMENTS: Package utility classes and helpers.
9  */
10 
11 #ifndef UT_PackageUtils_H
12 #define UT_PackageUtils_H
13 
14 #include "UT_API.h"
15 #include "UT_Array.h"
16 #include "UT_Assert.h"
17 #include "UT_DirUtil.h"
18 #include "UT_SharedPtr.h"
19 #include "UT_StringArray.h"
20 #include "UT_StringMap.h"
21 #include "UT_StringSet.h"
22 #include "UT_StringStream.h"
23 #include "UT_VarScan.h"
24 #include <SYS/SYS_ParseNumber.h>
25 #include <SYS/SYS_Platform.h>
26 #include <SYS/SYS_VersionUtil.h>
27 
28 #include <hboost/any.hpp>
29 #include <tools/henv.h>
30 #include <tools/hpath.h>
31 
32 #include <cctype>
33 #include <iostream>
34 
35 #ifdef NO_VALUE
36 #undef NO_VALUE
37 #endif
38 
39 namespace UT_Package
40 {
41 namespace utils
42 {
43 constexpr UT_StringLit klog_error = "ERROR";
44 constexpr UT_StringLit klog_info = "INFO";
45 constexpr UT_StringLit klog_warning = "WARNING";
47 
48 static const char *path_sep()
49 {
50  return PATH_SEP_STRING;
51 }
52 
53 static char path_sep_char()
54 {
55  return PATH_SEP_CHAR;
56 }
57 
58 static const char *vardef_sep()
59 {
60  return "-";
61 }
62 
63 static UT_StringHolder makeVarRef(const char * var_name, bool use_symbol=true,
64  const char * prefix=nullptr, const char * suffix=nullptr)
65 {
66  // note: this helper is typically used with utils::expandVar
67  UT_ASSERT(var_name != nullptr);
68  UT_WorkBuffer wb;
69  wb.format("{}{}{}{}", use_symbol ? "$" : "", prefix ? prefix : "", var_name, suffix ? suffix : "");
70  return wb;
71 }
72 
73 static void getBuildCompilerInfo(UT_StringHolder& out_name, exint& out_major, exint& out_minor)
74 {
75 #if defined(_MSC_VER)
76  out_name = "cl";
77  out_major = (_MSC_FULL_VER / 10000000) % 10000;
78  out_minor = (_MSC_FULL_VER / 100000) % 100;
79 
80 #elif defined(__clang__)
81  out_name = "clang";
82  out_major = __clang_major__;
83  out_minor = __clang_minor__;
84 
85 #elif defined(__GNUC__)
86  out_name = "gcc";
87  out_major = __GNUC__;
88  out_minor = __GNUC_MINOR__;
89 #else
90  out_name = "unknown";
91  out_major = NO_VALUE;
92  out_minor = NO_VALUE;
93 #endif
94 }
95 
96 /*
97 Strip some unwanted chars from a variable value string.
98 */
99 static UT_StringHolder cleanupValue(char const * value)
100 {
101  if (value)
102  {
103  static constexpr UT_StringLit kStripables = "\t\n\r";
104  UT_String sval(value);
105  sval.strip(kStripables.asHolder());
106  return sval.c_str();
107  }
108  return UT_StringHolder();
109 }
110 
111 /*
112 Build an array of unset variables found in a given value expression.
113 Update a dependency map to hold dependency information between variables.
114 May returns a list of variables marked as circular dependent.
115 */
116 UT_API extern bool buildVarDependency(
117  UT_StringHolder const& var_name,
118  const char * var_value,
119  UT_StringArray& unset_vars,
120  UT_StringMap<UT_StringSet>& vars_dep_map,
121  UT_StringMap<UT_StringSet>& vars_circ_dep);
122 
123 UT_API extern UT_StringHolder expandVar(const char *arg, bool want_marker);
124 UT_API extern UT_StringHolder makeVarRefPlatform(const char * var);
125 
126 UT_API extern bool isCmdShell();
127 UT_API extern const char *pathSepShell();
128 
129 // Normalizes and expands (optionally) a file path.
130 //
131 // file_path: Path to normalize. We use UT_String to be compatible
132 // with UTnormalizeFilePath which returns the normalized
133 // file path by arg reference.
134 // expand: Expands the content of file_path after the path has been
135 // normalized.
136 // want_marker: If true, expandVar returns `&` if the path is empty.
137 // Mostly used by HOUDINI_PATH like paths.
138 //
139 // always_want_expanded_path: Always keep the result of the expanded
140 // vars with the path even if the content
141 // is empty.
142 // Assumes the input is an environment variable value, potentially
143 // formatted as env var path.
144 UT_API extern void normalizeEnvVarPath(UT_String& file_path, bool want_marker=false, bool always_want_expanded_path=false);
145 UT_API extern void normalizePath(UT_String& file_path, bool want_marker=false, bool always_want_expanded_path=false);
146 UT_API extern void normalizePath(UT_StringHolder& file_path, bool want_marker=false, bool always_want_expanded_path=false);
147 // Returns a new normalized/expanded path
148 UT_API extern UT_StringHolder cnormalizePath(UT_StringHolder const & file_path, bool want_marker=false, bool always_want_expanded_path=false);
149 
150 struct Factory
151 {
152  template <typename T, typename... Args>
153  static UT_SharedPtr<T> make(Args &&... args)
154  {
155  return UTmakeShared<T>(std::forward<Args>(args)...);
156  }
157 };
158 
159 // Helper for handling Houdini version values
160 class HVersion
161 {
162 public:
164  : myMajor(-1)
165  , myMinor(-1)
166  , myBuild(-1)
167  , myPatch(-1)
168  {
169  }
170 
171  int compare( HVersion const & other, bool full=true ) const
172  {
173  if (full)
174  {
175  UT_ASSERT(other.myMajor > -1);
176 
177  // Assign other build + patch with this if not set (-1)
178  int other_minor = myMinor;
179  int other_build = myBuild;
180  int other_patch = myPatch;
181 
182  if (other.myMinor != -1)
183  {
184  other_minor = other.myMinor;
185  }
186 
187  if (other.myBuild != -1)
188  {
189  other_build = other.myBuild;
190  }
191 
192  if (other.myPatch != -1)
193  {
194  other_patch = other.myPatch;
195  }
196 
197  return SYSversionCompare(
198  myMajor, myMinor, myBuild, myPatch, other.myMajor, other_minor, other_build, other_patch);
199  }
200 
201  if (myMajor != other.myMajor)
202  {
203  return myMajor - other.myMajor;
204  }
205 
206  // compare the rest if the other components are provided (!= -1)
207 
208  if (other.myMinor != -1 && myMinor != other.myMinor)
209  {
210  return myMinor - other.myMinor;
211  }
212 
213  if (other.myBuild != -1 && myBuild != other.myBuild)
214  {
215  return myBuild - other.myBuild;
216  }
217  if (other.myPatch != -1 && myPatch != other.myPatch)
218  {
219  return myPatch - other.myPatch;
220  }
221  return 0;
222  }
223 
224  bool operator > (HVersion const & other) const
225  {
226  return compare(other) > 0;
227  }
228 
229  bool operator >= (HVersion const & other) const
230  {
231  return operator>(other) || operator==(other);
232  }
233 
234  bool operator < (HVersion const & other) const
235  {
236  return compare(other) < 0;
237  }
238 
239  bool operator <= (HVersion const & other) const
240  {
241  return operator<(other) || operator==(other);
242  }
243 
244  bool operator == (HVersion const & other) const
245  {
246  return compare(other,false /*full*/) == 0;
247  }
248 
249  static HVersion convert(UT_StringRef const & str)
250  {
251  UT_StringArray tokens;
252  UT_String(str.c_str()).tokenize( tokens, "." );
253 
254  HVersion hver;
255 
256  if (tokens.size() > 4)
257  {
258  // wrong format
259  return hver;
260  }
261  else if (tokens.size()==1)
262  {
263  hver.myMajor = SYSatoi(tokens[0].c_str());
264  }
265  else if (tokens.size()==2)
266  {
267  hver.myMajor = SYSatoi(tokens[0].c_str());
268  hver.myMinor = SYSatoi(tokens[1].c_str());
269  }
270  else if (tokens.size()==3)
271  {
272  hver.myMajor = SYSatoi(tokens[0].c_str());
273  hver.myMinor = SYSatoi(tokens[1].c_str());
274  hver.myBuild = SYSatoi(tokens[2].c_str());
275  }
276  else
277  {
278  hver.myMajor = SYSatoi(tokens[0].c_str());
279  hver.myMinor = SYSatoi(tokens[1].c_str());
280  hver.myBuild = SYSatoi(tokens[2].c_str());
281  hver.myPatch = SYSatoi(tokens[3].c_str());
282  }
283  return hver;
284  }
285 
286  int myMajor;
287  int myMinor;
288  int myBuild;
289  int myPatch;
290 };
291 
292 // Helper for handling Houdini python version with packages
294 {
295 public:
296  // Return the build version name
297  static char const* toString();
298 
300  : myMajor(-1)
301  , myMinor(-1)
302  , myMicro(-1)
303  {
304  }
305 
306  int compare( PYVersion const & other) const
307  {
308  if (myMajor != other.myMajor)
309  {
310  return myMajor - other.myMajor;
311  }
312 
313  if (myMinor == -1)
314  {
315  return 0;
316  }
317 
318  // compare the rest if the other components are provided (!= -1)
319 
320  if (other.myMinor != -1 && myMinor != other.myMinor)
321  {
322  return myMinor - other.myMinor;
323  }
324 
325  if (other.myMicro != -1 && myMicro != other.myMicro)
326  {
327  return myMicro - other.myMicro;
328  }
329 
330  return 0;
331  }
332 
333  bool operator > (PYVersion const & other) const
334  {
335  return compare(other) > 0;
336  }
337 
338  bool operator >= (PYVersion const & other) const
339  {
340  return operator>(other) || operator==(other);
341  }
342 
343  bool operator < (PYVersion const & other) const
344  {
345  return compare(other) < 0;
346  }
347 
348  bool operator <= (PYVersion const & other) const
349  {
350  return operator<(other) || operator==(other);
351  }
352 
353  bool operator == (PYVersion const & other) const
354  {
355  return compare(other) == 0;
356  }
357 
358  // Convert a string formatted python version to PYVersion
359  // pyver_str: <python><major>.<minor>.<micro>
360  // Note: minor and micro are optional
361  static PYVersion convert(char const * pyver_str)
362  {
363  PYVersion pyver;
364  UT_String str(pyver_str);
365 
366  if (!str || !str.startsWith("python"))
367  {
368  return pyver;
369  }
370 
371  // Remove the python token
372  str.eraseHead(6);
373 
374  UT_StringArray tokens;
375  str.tokenize(tokens, ".");
376 
377  if (tokens.size() > 3)
378  {
379  // wrong format
380  return pyver;
381  }
382  else if (tokens.size()==1)
383  {
384  pyver.myMajor = SYSatoi(tokens[0].c_str());
385  }
386  else if (tokens.size()==2)
387  {
388  pyver.myMajor = SYSatoi(tokens[0].c_str());
389  pyver.myMinor = SYSatoi(tokens[1].c_str());
390  }
391  else if (tokens.size()==3)
392  {
393  pyver.myMajor = SYSatoi(tokens[0].c_str());
394  pyver.myMinor = SYSatoi(tokens[1].c_str());
395  pyver.myMicro = SYSatoi(tokens[2].c_str());
396  }
397  return pyver;
398  }
399 
400  static void getVersion(PYVersion& pyver);
401 
402  int myMajor;
403  int myMinor;
404  int myMicro;
405 };
406 
407 // Helper for handling the compiler version used for building Houdini.
409 {
410 public:
412  : myMajor(NO_VALUE)
413  , myMinor(NO_VALUE)
414  {
415  }
416 
417  int compare(HPlatformBuildVersion const& other) const
418  {
419  if (myName != other.myName)
420  {
421  return -1;
422  }
423 
424  if (myMajor != NO_VALUE && other.myMajor != NO_VALUE && myMajor != other.myMajor)
425  {
426  return myMajor - other.myMajor;
427  }
428 
429  if (myMinor != NO_VALUE && other.myMinor != NO_VALUE && myMinor != other.myMinor)
430  {
431  return myMinor - other.myMinor;
432  }
433 
434  return 0;
435  }
436 
437  bool operator > (HPlatformBuildVersion const& other) const
438  {
439  return compare(other) > 0;
440  }
441 
442  bool operator >= (HPlatformBuildVersion const& other) const
443  {
444  return operator>(other) || operator==(other);
445  }
446 
447  bool operator < (HPlatformBuildVersion const& other) const
448  {
449  return compare(other) < 0;
450  }
451 
452  bool operator <= (HPlatformBuildVersion const& other) const
453  {
454  return operator<(other) || operator==(other);
455  }
456 
457  bool operator == (HPlatformBuildVersion const& other) const
458  {
459  return compare(other) == 0;
460  }
461 
462  // Convert a string formatted platform build version to HPlatformBuildVersion
463  // ver_str: <compiler name>.<major>.<minor>
464  static HPlatformBuildVersion convert(char const* ver_str)
465  {
466  HPlatformBuildVersion pbver;
467 
468  if (!ver_str || !strlen(ver_str))
469  {
470  return pbver;
471  }
472 
473  UT_StringArray tokens;
474  UT_String ut_ver_str(ver_str);
475  ut_ver_str.tokenize(tokens, ".");
476 
477  if (tokens.size() < 1 || tokens.size() > 3)
478  {
479  // wrong format
480  return pbver;
481  }
482 
483  if (tokens.size()==1)
484  {
485  pbver.myName = tokens[0].c_str();
486  }
487  else if (tokens.size()==2)
488  {
489  pbver.myName = tokens[0].c_str();
490  pbver.myMajor = SYSatoi(tokens[1].c_str());
491  }
492  else
493  {
494  pbver.myName = tokens[0].c_str();
495  pbver.myMajor = SYSatoi(tokens[1].c_str());
496  pbver.myMinor = SYSatoi(tokens[2].c_str());
497  }
498 
499  return pbver;
500  }
501 
502  void getVersion(UT_StringHolder& out_name, exint& out_major, exint& out_minor)
503  {
504  out_name = myName;
505  out_major = myMajor;
506  out_minor = myMinor;
507  }
508 
509  static
511  {
512  getBuildCompilerInfo(out_version.myName, out_version.myMajor, out_version.myMinor);
513  }
514 
515  // Build the version string. Supported formats:
516  // name.major.minor
517  // name.major
518  // name
520  {
521  if (myName.isEmpty())
522  {
523  static UT_StringHolder unknown("unknown");
524  return unknown;
525  }
526 
527  UT_WorkBuffer ver;
528  if (myMajor != NO_VALUE && myMinor != NO_VALUE)
529  ver.format("{}.{}.{}", myName, myMajor, myMinor);
530  else if (myMajor != NO_VALUE && myMinor == NO_VALUE)
531  ver.format("{}.{}", myName, myMajor);
532  else
533  ver.format("{}", myName);
534  return ver;
535  }
536 
540 };
541 
542 // Encapsulates variant values used by UT_Package
543 class Value
544 {
545 public:
547 
548  Value() = default;
549 
550  explicit Value(const char *value)
551  {
552  set(value);
553  }
554 
555  explicit Value(UT_StringRef const & value)
556  {
557  if (value.isstring())
558  {
559  myValue = std::string(value.c_str(), value.length());
560  }
561  else
562  {
563  myValue = std::string();
564  }
565  }
566 
567  explicit Value(fpreal64 value)
568  {
569  myValue = value;
570  }
571 
572  explicit Value(int64 value)
573  {
574  myValue = value;
575  }
576 
577  explicit Value(bool value)
578  {
579  myValue = value;
580  }
581 
582  explicit Value(HVersion value)
583  {
584  myValue = value;
585  }
586 
587  explicit Value(PYVersion value)
588  {
589  myValue = value;
590  }
591 
592  explicit Value(HPlatformBuildVersion value)
593  {
594  myValue = value;
595  }
596 
597  hboost::any const & value() const
598  {
599  return myValue;
600  }
601 
602  void set(const char *value)
603  {
604  if (value)
605  {
606  myValue = std::string(value, strlen(value));
607  }
608  else
609  {
610  myValue = std::string();
611  }
612  }
613 
614  void set(fpreal64 value)
615  {
616  myValue = value;
617  }
618 
619  void set(int64 value)
620  {
621  myValue = value;
622  }
623 
624  void set(bool value)
625  {
626  myValue = value;
627  }
628 
629  void set(HVersion value)
630  {
631  myValue = value;
632  }
633 
634  void set(PYVersion value)
635  {
636  myValue = value;
637  }
638 
640  {
641  myValue = value;
642  }
643 
645  {
646  return toWorkBuffer().buffer();
647  }
648 
650  {
651  UT_WorkBuffer wb;
652  if (isA<fpreal64>())
653  {
654  wb.format("{}", hboost::any_cast<fpreal64>(myValue));
655  }
656  else if (isA<int64>())
657  {
658  wb.format("{}", hboost::any_cast<int64>(myValue));
659  }
660  else if (isA<bool>())
661  {
662  wb.format("{}", hboost::any_cast<bool>(myValue) ? "1" : "0");
663  }
664  else if (isA<std::string>())
665  {
666  wb.format("{}",hboost::any_cast<std::string>(myValue));
667  }
668  else if (isA<HVersion>())
669  {
670  auto && hver = hboost::any_cast<HVersion>(myValue);
671  wb.format("{}.{}.{}.{}",hver.myMajor,hver.myMinor,hver.myBuild,hver.myPatch);
672  }
673  else if (isA<PYVersion>())
674  {
675  auto && pyver = hboost::any_cast<PYVersion>(myValue);
676  wb.format("python{}.{}", pyver.myMajor,pyver.myMinor);
677  }
678  else if (isA<HPlatformBuildVersion>())
679  {
680  auto&& hbc_ver = hboost::any_cast<HPlatformBuildVersion>(myValue);
681  wb = hbc_ver.toString();
682  }
683  else
684  {
685  UT_ASSERT(!"Unknown type in UT_Package::utils::Value");
686  }
687 
688  return wb;
689  }
690 
691  template <typename T>
692  T const & get() const
693  {
694  return hboost::any_cast<T const &>(myValue);
695  }
696 
697  template <typename T>
698  bool isA() const
699  {
700  return hboost::typeindex::type_id<T>() == myValue.type();
701  }
702 
703  bool valid() const
704  {
705  return !myValue.empty();
706  }
707 
708  bool isEqual(utils::Value const & other, bool ignore_case=false) const
709  {
710  if (isA<std::string>() && other.isA<std::string>())
711  {
712  if (ignore_case)
713  {
714  auto && lhs = hboost::any_cast<std::string>(myValue);
715  auto && rhs = hboost::any_cast<std::string>(other.value());
716  return compareIgnoreCase(lhs, rhs);
717  }
718  else
719  {
720  return get<std::string>() == other.get<std::string>();
721  }
722  }
723 
724  if (isA<int64>() && other.isA<int64>())
725  {
726  return get<int64>() == other.get<int64>();
727  }
728 
729  if (isA<fpreal64>() && other.isA<fpreal64>())
730  {
731  return get<fpreal64>() == other.get<fpreal64>();
732  }
733 
734  if (isA<bool>() && other.isA<bool>())
735  {
736  return get<bool>() == other.get<bool>();
737  }
738 
739  if (isA<HVersion>() && other.isA<HVersion>())
740  {
741  return get<HVersion>() == other.get<HVersion>();
742  }
743 
744  if (isA<HVersion>() && other.isA<std::string>())
745  {
746  HVersion hver = HVersion::convert(other.get<std::string>().c_str());
747  return get<HVersion>() == hver;
748  }
749 
750  if (isA<std::string>() && other.isA<HVersion>())
751  {
752  HVersion hver = HVersion::convert(get<std::string>().c_str());
753  return hver == other.get<HVersion>();
754  }
755 
756  if (isA<PYVersion>() && other.isA<PYVersion>())
757  {
758  return get<PYVersion>() == other.get<PYVersion>();
759  }
760 
761  if (isA<PYVersion>() && other.isA<std::string>())
762  {
763  PYVersion pyver = PYVersion::convert(other.get<std::string>().c_str());
764  return get<PYVersion>() == pyver;
765  }
766 
767  if (isA<std::string>() && other.isA<PYVersion>())
768  {
769  PYVersion pyver = PYVersion::convert(get<std::string>().c_str());
770  return pyver == other.get<PYVersion>();
771  }
772 
773  if (isA<HPlatformBuildVersion>() && other.isA<HPlatformBuildVersion>())
774  {
775  return get<HPlatformBuildVersion>() == other.get<HPlatformBuildVersion>();
776  }
777 
778  if (isA<HPlatformBuildVersion>() && other.isA<std::string>())
779  {
781  return get<HPlatformBuildVersion>() == pbver;
782  }
783 
784  if (isA<std::string>() && other.isA<HPlatformBuildVersion>())
785  {
786  HPlatformBuildVersion pbver = HPlatformBuildVersion::convert(get<std::string>().c_str());
787  return pbver == other.get<HPlatformBuildVersion>();
788  }
789 
790  throw std::runtime_error("utils::Value::isEqual: unsupported type");
791  }
792 
793  bool isGreater(utils::Value const & other) const
794  {
795  if ( isA<std::string>() && other.isA<std::string>() )
796  {
797  return get<std::string>() > other.get<std::string>();
798  }
799 
800  if (isA<HVersion>() && other.isA<HVersion>())
801  {
802  return get<HVersion>() > other.get<HVersion>();
803  }
804 
805  if (isA<HVersion>() && other.isA<std::string>())
806  {
807  HVersion hver = HVersion::convert(other.get<std::string>().c_str());
808  return get<HVersion>() > hver;
809  }
810 
811  if (isA<std::string>() && other.isA<HVersion>())
812  {
813  HVersion hver = HVersion::convert(get<std::string>().c_str());
814  return hver > other.get<HVersion>();
815  }
816 
817  if (isA<PYVersion>() && other.isA<PYVersion>())
818  {
819  return get<PYVersion>() > other.get<PYVersion>();
820  }
821 
822  if (isA<PYVersion>() && other.isA<std::string>())
823  {
824  PYVersion pyver = PYVersion::convert(other.get<std::string>().c_str());
825  return get<PYVersion>() > pyver;
826  }
827 
828  if (isA<std::string>() && other.isA<PYVersion>())
829  {
830  PYVersion pyver = PYVersion::convert(get<std::string>().c_str());
831  return pyver > other.get<PYVersion>();
832  }
833 
834  if (isA<HPlatformBuildVersion>() && other.isA<HPlatformBuildVersion>())
835  {
836  return get<HPlatformBuildVersion>() > other.get<HPlatformBuildVersion>();
837  }
838 
839  if (isA<HPlatformBuildVersion>() && other.isA<std::string>())
840  {
842  return get<HPlatformBuildVersion>() > pbver;
843  }
844 
845  if (isA<std::string>() && other.isA<HPlatformBuildVersion>())
846  {
847  HPlatformBuildVersion pbver = HPlatformBuildVersion::convert(get<std::string>().c_str());
848  return pbver > other.get<HPlatformBuildVersion>();
849  }
850 
851  if ( isA<std::string>() || other.isA<std::string>() )
852  {
853  throw std::runtime_error("utils::Value::isGreater: unsupported types");
854  }
855 
856  return get<fpreal64>() > other.get<fpreal64>();
857  }
858 
859  bool isGreaterEqual(utils::Value const & other) const
860  {
861  return isGreater(other) || isEqual(other);
862  }
863 
864  bool isLess(utils::Value const & other) const
865  {
866  if ( isA<std::string>() && other.isA<std::string>() )
867  {
868  return get<std::string>() < other.get<std::string>();
869  }
870 
871  if (isA<HVersion>() && other.isA<HVersion>())
872  {
873  return get<HVersion>() < other.get<HVersion>();
874  }
875 
876  if (isA<HVersion>() && other.isA<std::string>())
877  {
878  HVersion hver = HVersion::convert(other.get<std::string>().c_str());
879  return get<HVersion>() < hver;
880  }
881 
882  if (isA<std::string>() && other.isA<HVersion>())
883  {
884  HVersion hver = HVersion::convert(get<std::string>().c_str());
885  return hver < other.get<HVersion>();
886  }
887 
888  if (isA<PYVersion>() && other.isA<PYVersion>())
889  {
890  return get<PYVersion>() < other.get<PYVersion>();
891  }
892 
893  if (isA<PYVersion>() && other.isA<std::string>())
894  {
895  PYVersion pyver = PYVersion::convert(other.get<std::string>().c_str());
896  return get<PYVersion>() < pyver;
897  }
898 
899  if (isA<std::string>() && other.isA<PYVersion>())
900  {
901  PYVersion pyver = PYVersion::convert(get<std::string>().c_str());
902  return pyver < other.get<PYVersion>();
903  }
904 
905  if (isA<HPlatformBuildVersion>() && other.isA<HPlatformBuildVersion>())
906  {
907  return get<HPlatformBuildVersion>() < other.get<HPlatformBuildVersion>();
908  }
909 
910  if (isA<HPlatformBuildVersion>() && other.isA<std::string>())
911  {
913  return get<HPlatformBuildVersion>() < pbver;
914  }
915 
916  if (isA<std::string>() && other.isA<HPlatformBuildVersion>())
917  {
918  HPlatformBuildVersion pbver = HPlatformBuildVersion::convert(get<std::string>().c_str());
919  return pbver < other.get<HPlatformBuildVersion>();
920  }
921 
922  if ( isA<std::string>() || other.isA<std::string>() )
923  {
924  throw std::runtime_error("utils::Value::isLess: unsupported types");
925  }
926 
927  return get<fpreal64>() < other.get<fpreal64>();
928  }
929 
930  bool isLessEqual(utils::Value const & other) const
931  {
932  return isLess(other) || isEqual(other);
933  }
934 
935  // Substiture all occurances of find with replace_with
936  bool substitute(char const* find, char const* replace_with)
937  {
938  if (valid() && isA<std::string>())
939  {
940  auto && to_replace = get<std::string>();
941  UT_WorkBuffer wb(to_replace.c_str());
942  if (wb.substitute(find, replace_with))
943  {
944  set(wb.buffer());
945  return true;
946  }
947  }
948  return false;
949  }
950 
951 private:
952  bool compareIgnoreCase(std::string & s1, std::string & s2) const
953  {
954  return ((s1.size() == s2.size()) &&
955  std::equal(s1.begin(), s1.end(), s2.begin(),
956  [](char & c1, char & c2)
957  {
958  return (c1 == c2 || std::toupper(c1) == std::toupper(c2));
959  }
960  ));
961  }
962  hboost::any myValue;
963 }; // Value
964 
965 // Loggger to hold warning/errors/info messages
966 class Logger
967 {
968 public:
971 
972  enum class Flags : unsigned
973  {
974  all,
975  info,
976  warning,
977  error
978  };
979 
981  : myHasErrorFlag(false)
982  , myLog(&myDefaultLog)
983  , myVerboseFlag(false)
984  {
985  }
986 
987  void setAsVerbose(bool flag)
988  {
989  myVerboseFlag = flag;
990  }
991 
992  bool verbose() const
993  {
994  return myVerboseFlag;
995  }
996 
997  void error(char const* msg)
998  {
999  addToBuffer(klog_error.asHolder(), msg);
1000  if (msg)
1001  {
1002  myHasErrorFlag = true;
1003  }
1004  }
1005 
1006  template< typename ...Args >
1007  void error(char const* msg, Args&&... args)
1008  {
1009  addToBuffer(klog_error.asHolder(), formatMsg(msg, std::forward<Args>(args)...));
1010  if (msg)
1011  {
1012  myHasErrorFlag = true;
1013  }
1014  }
1015 
1016  void info(char const* msg)
1017  {
1018  if (!myVerboseFlag)
1019  {
1020  return;
1021  }
1022  addToBuffer(klog_info.asHolder(), msg);
1023  }
1024 
1025  template< typename ...Args >
1026  void info(char const* msg, Args&&... args)
1027  {
1028  if (!myVerboseFlag)
1029  {
1030  return;
1031  }
1032  addToBuffer(klog_info.asHolder(), formatMsg(msg, std::forward<Args>(args)...));
1033  }
1034 
1035  void message(char const* msg)
1036  {
1037  if (!myVerboseFlag)
1038  {
1039  return;
1040  }
1041  addToBuffer(nullptr, msg);
1042  }
1043 
1044  template< typename ...Args >
1045  void message(char const* msg, Args&&... args)
1046  {
1047  if (!myVerboseFlag)
1048  {
1049  return;
1050  }
1051  addToBuffer(nullptr, formatMsg(msg, std::forward<Args>(args)...));
1052  }
1053 
1054  void warning(char const* msg)
1055  {
1056  addToBuffer(klog_warning.asHolder(), msg);
1057  }
1058 
1059  template< typename ...Args >
1060  void warning(char const* msg, Args&&... args)
1061  {
1062  addToBuffer(klog_warning.asHolder(), formatMsg(msg, std::forward<Args>(args)...));
1063  }
1064 
1065  void clear()
1066  {
1067  myDefaultLog.clear();
1068  myEntryMap.clear();
1069  myEntryArray.clear();
1070  myErrorArray.clear();
1071  myWarningArray.clear();
1072  myHasErrorFlag = false;
1073  }
1074 
1076  {
1077  myErrorArray.clear();
1078  myHasErrorFlag = false;
1079  }
1080 
1081  void toStream(std::ostream &os) const
1082  {
1083  for (auto && entry : myEntryArray)
1084  {
1085  os << entry.c_str() << std::endl;
1086  auto && it = myEntryMap.find(entry);
1087  os << it->second.c_str() << std::endl;
1088  }
1089 
1090  if (myDefaultLog)
1091  {
1092  os << myDefaultLog.c_str() << std::endl;
1093  }
1094  }
1095 
1096  UT_StringHolder toString(bool header=true) const
1097  {
1098  UT_OStringStream ss;
1099  toStream(ss);
1101  if (header && myVerboseFlag)
1102  {
1103  log += "= = = Houdini Package log = = =\n";
1104  }
1105 
1106  log += ss.str().buffer();
1107 
1108  if (header && myVerboseFlag)
1109  {
1110  log += "= = = = = = = = = = = = = = = =\n";
1111  }
1112  return log;
1113  }
1114 
1115  UT_StringArray const & errors() const
1116  {
1117  return myErrorArray;
1118  }
1119 
1120  UT_StringArray const & warnings() const
1121  {
1122  return myWarningArray;
1123  }
1124 
1125  void log(char const* title, Flags flags=Flags::all) const
1126  {
1127  if (flags == Flags::all)
1128  {
1129  std::cout << title << std::endl;
1130  toStream(std::cout);
1131  }
1132  else if (myHasErrorFlag && flags == Flags::error)
1133  {
1134  std::cerr << title << std::endl;
1135  toStream(std::cerr);
1136  }
1137  }
1138 
1139  void start(char const * entry)
1140  {
1141  if (!entry)
1142  {
1143  // global logging
1144  myLog = &myDefaultLog;
1145  return;
1146  }
1147 
1148  // logging done per entry
1149  if (!myEntryMap.count(entry))
1150  {
1151  myEntryMap[entry] = UT_StringHolder();
1152  myEntryArray.append(entry);
1153  }
1154  myLog = &myEntryMap[entry];
1155  }
1156 
1157  bool hasErrors() const
1158  {
1159  return myHasErrorFlag;
1160  }
1161 
1162  void append(Logger const & logger)
1163  {
1164  UT_OStringStream ss;
1165  logger.toStream(ss);
1166 
1167  UT_WorkBuffer wb;
1168  wb += ss.str().buffer();
1169 
1170  if (wb.buffer())
1171  {
1172  buffer() += wb.buffer();
1173  }
1174  }
1175 
1176 private:
1177  template< typename ...Args >
1178  UT_StringHolder formatMsg( const char* format, Args &&... args )
1179  {
1180  UT_WorkBuffer wb;
1181  wb.format(format, args...);
1182  return wb;
1183  }
1184 
1185  void addToBuffer(const char* prefix, const char* msg)
1186  {
1187  if (!msg || !strlen(msg))
1188  {
1189  return;
1190  }
1191 
1192  if (prefix)
1193  {
1194  buffer() += prefix;
1195  buffer() += ": ";
1196  }
1197  buffer() += msg;
1198  buffer() += "\n";
1199 
1200  if ( msg && prefix && klog_error.asHolder().equal(prefix))
1201  {
1202  myErrorArray.append(msg);
1203  }
1204  else if ( msg && prefix && klog_warning.asHolder().equal(prefix))
1205  {
1206  myWarningArray.append(msg);
1207  }
1208  }
1209 
1210  UT_StringHolder & buffer()
1211  {
1212  return *myLog;
1213  }
1214 
1215  UT_StringHolder const & buffer() const
1216  {
1217  return *myLog;
1218  }
1219 
1220  EntryArray myEntryArray;
1221  EntryMap myEntryMap;
1222  UT_StringHolder* myLog;
1223  UT_StringHolder myDefaultLog;
1224  UT_StringArray myWarningArray;
1225  UT_StringArray myErrorArray;
1226  bool myHasErrorFlag;
1227  bool myVerboseFlag;
1228 }; // Logger
1229 
1230 } // utils
1231 } // UT_Package
1232 
1233 #endif // UT_PackageUtils_H
bool isGreaterEqual(utils::Value const &other) const
std::string ignore_case(std::string item)
Helper function to allow ignore_case to be passed to IsMember or Transform.
Definition: CLI11.h:3456
GLbitfield flags
Definition: glcorearb.h:1596
int getVersion(int version)
Definition: ImfVersion.h:99
UT_API void normalizePath(UT_String &file_path, bool want_marker=false, bool always_want_expanded_path=false)
bool isGreater(utils::Value const &other) const
bool operator>(HVersion const &other) const
UT_API bool buildVarDependency(UT_StringHolder const &var_name, const char *var_value, UT_StringArray &unset_vars, UT_StringMap< UT_StringSet > &vars_dep_map, UT_StringMap< UT_StringSet > &vars_circ_dep)
UT_StringHolder toString(bool header=true) const
void start(char const *entry)
#define PATH_SEP_STRING
Definition: hpath.h:33
void set(HVersion value)
bool operator>=(HVersion const &other) const
SYS_FORCE_INLINE void clear()
int compare(HVersion const &other, bool full=true) const
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
void getVersion(UT_StringHolder &out_name, exint &out_major, exint &out_minor)
bool operator<(HVersion const &other) const
bool isEmpty() const
Same as !isstring()
UT_API UT_StringHolder makeVarRefPlatform(const char *var)
int64 exint
Definition: SYS_Types.h:125
#define SYS_INT64_MAX
Definition: SYS_Types.h:176
SYS_FORCE_INLINE const char * buffer() const
void info(char const *msg, Args &&...args)
int compare(PYVersion const &other) const
int substitute(const char *find, const char *replacement, int count=-1)
An output stream object that owns its own string buffer storage.
void message(char const *msg)
IMATH_HOSTDEVICE constexpr bool equal(T1 a, T2 b, T3 t) IMATH_NOEXCEPT
Definition: ImathFun.h:105
#define UT_API
Definition: UT_API.h:14
bool equal(const UT_StringRef &str, bool ignore_case=false) const
void message(char const *msg, Args &&...args)
bool substitute(char const *find, char const *replace_with)
#define PATH_SEP_CHAR
Definition: hpath.h:32
bool operator<=(HVersion const &other) const
UT_StringArray const & errors() const
void clear()
Definition: UT_Map.h:184
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
Definition: core.h:1736
const UT_WorkBuffer & str()
Returns a read-only reference to the underlying UT_WorkBuffer.
exint size() const
Definition: UT_Array.h:646
OIIO_FORCEINLINE vbool4 operator>=(const vint4 &a, const vint4 &b)
Definition: simd.h:4577
void toStream(std::ostream &os) const
bool operator==(HPlatformBuildVersion const &other) const
double fpreal64
Definition: SYS_Types.h:201
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:137
void error(char const *msg, Args &&...args)
CompareResults OIIO_API compare(const ImageBuf &A, const ImageBuf &B, float failthresh, float warnthresh, ROI roi={}, int nthreads=0)
OIIO_FORCEINLINE vbool4 operator>(const vint4 &a, const vint4 &b)
Definition: simd.h:4561
OIIO_FORCEINLINE vbool4 operator<=(const vint4 &a, const vint4 &b)
Definition: simd.h:4581
UT_StringHolder toString() const
void set(PYVersion value)
Definition: core.h:760
void set(HPlatformBuildVersion value)
int tokenize(char *argv[], int max_args, char separator)
Definition: UT_String.h:842
bool any(const vbool4 &v)
Definition: simd.h:3468
exint length() const
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
Definition: UT_SharedPtr.h:36
UT_API const char * pathSepShell()
UT_WorkBuffer toWorkBuffer() const
UT_StringArray const & warnings() const
bool isLess(utils::Value const &other) const
hboost::any const & value() const
GLint GLint GLsizei GLint GLenum format
Definition: glcorearb.h:108
Value(UT_StringRef const &value)
static UT_SharedPtr< T > make(Args &&...args)
static void getVersion(HPlatformBuildVersion &out_version)
UT_API UT_StringHolder expandVar(const char *arg, bool want_marker)
static PYVersion convert(char const *pyver_str)
bool operator<(const GU_TetrahedronFacet &a, const GU_TetrahedronFacet &b)
void set(const char *value)
long long int64
Definition: SYS_Types.h:116
bool isEqual(utils::Value const &other, bool ignore_case=false) const
SYS_FORCE_INLINE const char * c_str() const
void error(char const *msg)
void warning(char const *msg, Args &&...args)
int eraseHead(int len)
Definition: UT_String.h:1098
UT_API UT_StringHolder cnormalizePath(UT_StringHolder const &file_path, bool want_marker=false, bool always_want_expanded_path=false)
constexpr UT_StringLit klog_error
exint append()
Definition: UT_Array.h:142
Definition: oidn.hpp:29
bool operator==(HVersion const &other) const
void append(Logger const &logger)
UT_StringMap< UT_StringHolder > EntryMap
UT_API void normalizeEnvVarPath(UT_String &file_path, bool want_marker=false, bool always_want_expanded_path=false)
size_t format(const char *fmt, const Args &...args)
int compare(HPlatformBuildVersion const &other) const
constexpr UT_StringLit klog_info
bool operator<(HPlatformBuildVersion const &other) const
void log(char const *title, Flags flags=Flags::all) const
UT_API bool isCmdShell()
constexpr UT_StringLit klog_warning
SYS_FORCE_INLINE const UT_StringHolder & asHolder() const
bool operator>=(HPlatformBuildVersion const &other) const
Value(const char *value)
**If you just want to fire and args
Definition: thread.h:609
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
Definition: core.h:1131
void info(char const *msg)
void clear()
Resets list to an empty list.
Definition: UT_Array.h:729
static HVersion convert(UT_StringRef const &str)
void setAsVerbose(bool flag)
bool startsWith(const UT_StringView &prefix, bool case_sensitive=true) const
void warning(char const *msg)
T const & get() const
bool operator<=(HPlatformBuildVersion const &other) const
void set(fpreal64 value)
bool isLessEqual(utils::Value const &other) const
constexpr exint NO_VALUE
Value(HPlatformBuildVersion value)
bool operator>(HPlatformBuildVersion const &other) const
SYS_FORCE_INLINE bool isstring() const
static HPlatformBuildVersion convert(char const *ver_str)
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition: core.h:2089