LibraryLink Utilities  3.0.1
Modern C++ wrapper over LibraryLink and WSTP
WSStream.hpp
Go to the documentation of this file.
1 
7 #ifndef LLU_WSTP_WSSTREAM_HPP_
8 #define LLU_WSTP_WSSTREAM_HPP_
9 
10 #include <algorithm>
11 #include <iterator>
12 #include <map>
13 #include <stack>
14 #include <type_traits>
15 #include <utility>
16 #include <vector>
17 
18 #include "wstp.h"
19 
20 #include "LLU/ErrorLog/Errors.h"
21 #include "LLU/Utilities.hpp"
22 
23 #include "LLU/WSTP/Get.h"
24 #include "LLU/WSTP/Put.h"
25 #include "LLU/WSTP/Strings.h"
26 #include "LLU/WSTP/Utilities.h"
28 
29 namespace LLU {
30 
40  template<WS::Encoding EncodingIn, WS::Encoding EncodingOut = EncodingIn>
41  class WSStream {
42  public:
47  explicit WSStream(WSLINK mlp);
48 
54  WSStream(WSLINK mlp, int argc);
55 
66  WSStream(WSLINK mlp, const std::string& head, int argc);
67 
71  ~WSStream() = default;
72 
76  WSLINK& get() noexcept {
77  return m;
78  }
79 
87  template<typename Iterator, typename = enable_if_input_iterator<Iterator>>
88  void sendRange(Iterator begin, Iterator end);
89 
98  template<typename Iterator, typename = enable_if_input_iterator<Iterator>>
99  void sendRange(Iterator begin, Iterator end, const std::string& head);
100 
101  public:
103  using StreamToken = WSStream& (*)(WSStream&);
104 
107 
109  using LoopbackData = std::pair<std::string, WSLINK>;
110 
111  //
112  // operator<<
113  //
114 
120 
126 
134 
142 
150 
156 
162 
168 
176 
184 
193  template<typename T>
195 
204  template<typename T>
206 
213  template<typename T, typename D>
214  WSStream& operator<<(const std::unique_ptr<T, D>& p);
215 
223  template<typename T>
224  WSStream& operator<<(const std::vector<T>& l);
225 
234  template<WS::Encoding E>
236 
254  template<WS::Encoding E, typename T>
256 
266  template<typename T>
267  WSStream& operator<<(const std::basic_string<T>& s);
268 
278  template<typename T, std::size_t N, typename = std::enable_if_t<WS::StringTypeQ<T>>>
279  WSStream& operator<<(const T (&s)[N]);
280 
288  WSStream& operator<<(const char* s);
289 
298  template<typename K, typename V>
299  WSStream& operator<<(const std::map<K, V>& map);
300 
310  template<typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
311  WSStream& operator<<(T value);
312 
322  template<typename Container, typename = std::void_t<
323  decltype(std::declval<Container>().begin(), std::declval<Container>().end(), std::declval<Container>().size())>>
324  WSStream& operator<<(const Container& c) {
325  sendRange(c.begin(), c.end());
326  return *this;
327  }
328 
329  //
330  // operator>>
331  //
332 
338 
349 
361 
372 
383 
390  WSStream& operator>>(bool& b);
391 
398  WSStream& operator>>(mint& i);
399 
408  template<typename T>
410 
419  template<typename T>
421 
429  template<typename T>
430  WSStream& operator>>(std::vector<T>& l);
431 
440  template<WS::Encoding E = EncodingIn>
442 
453  template<typename T>
454  WSStream& operator>>(std::basic_string<T>& s);
455 
464  template<WS::Encoding E, typename T>
466 
477  template<typename K, typename V>
478  WSStream& operator>>(std::map<K, V>& map);
479 
489  template<typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
490  WSStream& operator>>(T& value);
491 
492  private:
501  void check(int statusOk, const std::string& errorName, const std::string& debugInfo = "");
502 
510  int testHead(const std::string& head);
511 
519  void testHead(const std::string& head, int argc);
520 
524  void refreshCurrentWSLINK();
525 
526  private:
528  WSLINK m {};
529 
533  std::stack<LoopbackData> loopbackStack;
534 
536  bool currentExprDropped = false;
537  };
538 
540 
541  template<WS::Encoding EIn, WS::Encoding EOut>
542  WSStream<EIn, EOut>::WSStream(WSLINK mlp) : m(mlp), loopbackStack(std::deque<LoopbackData> {{"", mlp}}) {
543  if (!mlp) {
544  WS::Detail::throwLLUException(ErrorName::WSNullWSLinkError);
545  }
546  }
547 
548  template<WS::Encoding EIn, WS::Encoding EOut>
549  WSStream<EIn, EOut>::WSStream(WSLINK mlp, int argc) : WSStream(mlp, "List", argc) {}
550 
551  template<WS::Encoding EIn, WS::Encoding EOut>
552  WSStream<EIn, EOut>::WSStream(WSLINK mlp, const std::string& head, int argc) : WSStream(mlp) {
553  testHead(head, argc);
554  }
555 
556  template<WS::Encoding EIn, WS::Encoding EOut>
557  template<typename Iterator, typename>
558  void WSStream<EIn, EOut>::sendRange(Iterator begin, Iterator end) {
559  sendRange(begin, end, "List");
560  }
561 
562  template<WS::Encoding EIn, WS::Encoding EOut>
563  template<typename Iterator, typename>
564  void WSStream<EIn, EOut>::sendRange(Iterator begin, Iterator end, const std::string& head) {
565  *this << WS::Function(head, static_cast<int>(std::distance(begin, end)));
566  std::for_each(begin, end, [this](const auto& elem) { *this << elem; });
567  }
568 
569  template<WS::Encoding EIn, WS::Encoding EOut>
570  void WSStream<EIn, EOut>::check(int statusOk, const std::string& errorName, const std::string& debugInfo) {
571  WS::Detail::checkError(m, statusOk, errorName, debugInfo);
572  }
573 
574  template<WS::Encoding EIn, WS::Encoding EOut>
575  int WSStream<EIn, EOut>::testHead(const std::string& head) {
576  int argcount {};
577  check(WSTestHead(m, head.c_str(), &argcount), ErrorName::WSTestHeadError, "Expected \"" + head + "\"");
578  return argcount;
579  }
580 
581  template<WS::Encoding EIn, WS::Encoding EOut>
582  void WSStream<EIn, EOut>::testHead(const std::string& head, int argc) {
583  int argcount = testHead(head);
584  if (argc != argcount) {
585  WS::Detail::throwLLUException(ErrorName::WSTestHeadError, "Expected " + std::to_string(argc) + " arguments but got " + std::to_string(argcount));
586  }
587  }
588 
589  template<WS::Encoding EIn, WS::Encoding EOut>
590  void WSStream<EIn, EOut>::refreshCurrentWSLINK() {
591  if (loopbackStack.empty()) {
592  WS::Detail::throwLLUException(ErrorName::WSLoopbackStackSizeError, "Stack is empty in refreshCurrentWSLINK()");
593  }
594  m = std::get<WSLINK>(loopbackStack.top());
595  }
596 
597  //
598  // Definitions of WSStream<EIn, EOut>::operator<<
599  //
600 
601  template<WS::Encoding EIn, WS::Encoding EOut>
602  auto WSStream<EIn, EOut>::operator<<(StreamToken f) -> WSStream& {
603  return f(*this);
604  }
605 
606  template<WS::Encoding EIn, WS::Encoding EOut>
607  auto WSStream<EIn, EOut>::operator<<(BidirStreamToken f) -> WSStream& {
608  return f(*this, WS::Direction::Put);
609  }
610 
611  template<WS::Encoding EIn, WS::Encoding EOut>
612  auto WSStream<EIn, EOut>::operator<<(const WS::Symbol& s) -> WSStream& {
613  check(WSPutSymbol(m, s.getHead().c_str()), ErrorName::WSPutSymbolError, "Cannot put symbol: \"" + s.getHead() + "\"");
614  return *this;
615  }
616 
617  template<WS::Encoding EIn, WS::Encoding EOut>
618  auto WSStream<EIn, EOut>::operator<<(const WS::Function& f) -> WSStream& {
619  check(WSPutFunction(m, f.getHead().c_str(), f.getArgc()), ErrorName::WSPutFunctionError,
620  "Cannot put function: \"" + f.getHead() + "\" with " + std::to_string(f.getArgc()) + " arguments");
621  return *this;
622  }
623 
624  template<WS::Encoding EIn, WS::Encoding EOut>
625  auto WSStream<EIn, EOut>::operator<<(const WS::Missing& f) -> WSStream& {
626  check(WSPutFunction(m, f.getHead().c_str(), 1), // f.getArgc() could be 0 but we still want to send f.reason, even if it's an empty string
627  ErrorName::WSPutFunctionError, "Cannot put function: \"" + f.getHead() + "\" with 1 argument");
628  *this << f.why();
629  return *this;
630  }
631 
632  template<WS::Encoding EIn, WS::Encoding EOut>
633  auto WSStream<EIn, EOut>::operator<<(const WS::BeginExpr& expr) -> WSStream& {
634 
635  // reset dropped expression flag
636  currentExprDropped = false;
637 
638  // create a new LoopbackLink for the expression
639  auto* loopback = WS::Detail::getNewLoopback(m);
640 
641  // store expression head together with the link on the stack
642  loopbackStack.emplace(expr.getHead(), loopback);
643 
644  // active WSLINK changes
645  refreshCurrentWSLINK();
646 
647  return *this;
648  }
649 
650  template<WS::Encoding EIn, WS::Encoding EOut>
651  auto WSStream<EIn, EOut>::operator<<(const WS::DropExpr& /*tag*/) -> WSStream& {
652  // check if the stack has reasonable size
653  if (loopbackStack.size() < 2) {
654  WS::Detail::throwLLUException(ErrorName::WSLoopbackStackSizeError,
655  "Trying to Drop expression with loopback stack size " + std::to_string(loopbackStack.size()));
656  }
657  // we are dropping the expression so just close the link and hope that WSTP will do the cleanup
658  WSClose(std::get<WSLINK>(loopbackStack.top()));
659  loopbackStack.pop();
660  refreshCurrentWSLINK();
661 
662  // set the dropped expression flag
663  currentExprDropped = true;
664 
665  return *this;
666  }
667 
668  template<WS::Encoding EIn, WS::Encoding EOut>
669  auto WSStream<EIn, EOut>::operator<<(const WS::EndExpr& /*tag*/) -> WSStream& {
670 
671  // if the expression has been dropped at some point, then just reset the flag and do nothing as the loopback link no longer exists
672  if (currentExprDropped) {
673  currentExprDropped = false;
674  return *this;
675  }
676 
677  // check if the stack has reasonable size
678  if (loopbackStack.size() < 2) {
679  WS::Detail::throwLLUException(ErrorName::WSLoopbackStackSizeError,
680  "Trying to End expression with loopback stack size " + std::to_string(loopbackStack.size()));
681  }
682 
683  // extract active loopback link and expression head
684  auto currentPartialExpr = loopbackStack.top();
685  loopbackStack.pop();
686 
687  // active WSLINK changes
688  refreshCurrentWSLINK();
689 
690  // now count the expressions accumulated in the loopback link and send them to the parent link after the head
691  auto& exprArgs = std::get<WSLINK>(currentPartialExpr);
692  auto argCnt = WS::Detail::countExpressionsInLoopbackLink(exprArgs);
693  *this << WS::Function(std::get<std::string>(currentPartialExpr), argCnt);
694  check(WSTransferToEndOfLoopbackLink(m, exprArgs), ErrorName::WSTransferToLoopbackError,
695  "Could not transfer " + std::to_string(argCnt) + " expressions from Loopback Link");
696  // finally, close the loopback link
697  WSClose(exprArgs);
698 
699  return *this;
700  }
701 
702  template<WS::Encoding EIn, WS::Encoding EOut>
703  auto WSStream<EIn, EOut>::operator<<(bool b) -> WSStream& {
704  return *this << WS::Symbol(b ? "True" : "False");
705  }
706 
707  template<WS::Encoding EIn, WS::Encoding EOut>
708  auto WSStream<EIn, EOut>::operator<<(mint i) -> WSStream& {
709  WS::PutScalar<wsint64>::put(m, static_cast<wsint64>(i));
710  return *this;
711  }
712 
713  template<WS::Encoding EIn, WS::Encoding EOut>
714  template<typename T>
715  auto WSStream<EIn, EOut>::operator<<(const WS::ArrayData<T>& a) -> WSStream& {
716  const auto& del = a.get_deleter();
717  WS::PutArray<T>::put(m, a.get(), del.getDims(), del.getHeads(), del.getRank());
718  return *this;
719  }
720 
721  template<WS::Encoding EIn, WS::Encoding EOut>
722  template<typename T>
723  auto WSStream<EIn, EOut>::operator<<(const WS::ListData<T>& l) -> WSStream& {
724  const auto& del = l.get_deleter();
725  WS::PutList<T>::put(m, l.get(), del.getLength());
726  return *this;
727  }
728 
729  template<WS::Encoding EIn, WS::Encoding EOut>
730  template<typename T, typename D>
731  auto WSStream<EIn, EOut>::operator<<(const std::unique_ptr<T, D>& p) -> WSStream& {
732  if (p) {
733  *this << *p;
734  } else {
735  *this << WS::Null;
736  }
737  return *this;
738  }
739 
740  template<WS::Encoding EIn, WS::Encoding EOut>
741  template<typename T>
742  auto WSStream<EIn, EOut>::operator<<(const std::vector<T>& l) -> WSStream& {
743  if constexpr (WS::ScalarSupportedTypeQ<T>) {
744  WS::PutList<T>::put(m, l.data(), static_cast<int>(l.size()));
745  } else {
746  *this << WS::List(static_cast<int>(l.size()));
747  for (const auto& elem : l) {
748  *this << elem;
749  }
750  }
751  return *this;
752  }
753 
754  template<WS::Encoding EIn, WS::Encoding EOut>
755  template<WS::Encoding E>
756  auto WSStream<EIn, EOut>::operator<<(const WS::StringData<E>& s) -> WSStream& {
757  WS::String<E>::put(m, s.get(), s.get_deleter().getLength());
758  return *this;
759  }
760 
761  template<WS::Encoding EIn, WS::Encoding EOut>
762  template<typename T>
763  auto WSStream<EIn, EOut>::operator<<(const std::basic_string<T>& s) -> WSStream& {
764  if constexpr (WS::StringTypeQ<T>) {
765  WS::String<EOut>::put(m, s.c_str(), static_cast<int>(s.size()));
766  } else {
767  static_assert(dependent_false_v<T>, "Calling operator<< with unsupported character type.");
768  }
769  return *this;
770  }
771 
772  template<WS::Encoding EIn, WS::Encoding EOut>
773  template<typename T, std::size_t N, typename>
774  auto WSStream<EIn, EOut>::operator<<(const T (&s)[N]) -> WSStream& {
775  WS::String<EOut>::put(m, s, N);
776  return *this;
777  }
778 
779  template<WS::Encoding EIn, WS::Encoding EOut>
780  template<WS::Encoding E, typename T>
781  auto WSStream<EIn, EOut>::operator<<(const WS::PutAs<E, T>& wrp) -> WSStream& {
782  WSStream<EIn, E> tmpWSS {m};
783  tmpWSS << wrp.obj;
784  return *this;
785  }
786 
787  template<WS::Encoding EIn, WS::Encoding EOut>
788  auto WSStream<EIn, EOut>::operator<<(const char* s) -> WSStream& {
789  WS::String<EOut>::put(m, s, static_cast<int>(std::strlen(s)));
790  return *this;
791  }
792 
793  template<WS::Encoding EIn, WS::Encoding EOut>
794  template<typename T, typename>
795  auto WSStream<EIn, EOut>::operator<<(T value) -> WSStream& {
796  if constexpr (WS::ScalarSupportedTypeQ<T>) {
797  WS::PutScalar<T>::put(m, value);
798  } else {
799  static_assert(dependent_false_v<T>, "Calling operator<< with unsupported scalar type.");
800  }
801  return *this;
802  }
803 
804  template<WS::Encoding EIn, WS::Encoding EOut>
805  template<typename K, typename V>
806  auto WSStream<EIn, EOut>::operator<<(const std::map<K, V>& map) -> WSStream& {
807  *this << WS::Association(static_cast<int>(map.size()));
808  for (const auto& elem : map) {
809  *this << WS::Rule << elem.first << elem.second;
810  }
811  return *this;
812  }
813 
814  //
815  // Definitions of WSStream<EIn, EOut>::operator>>
816  //
817 
818  template<WS::Encoding EIn, WS::Encoding EOut>
819  auto WSStream<EIn, EOut>::operator>>(BidirStreamToken f) -> WSStream& {
820  return f(*this, WS::Direction::Get);
821  }
822 
823  template<WS::Encoding EIn, WS::Encoding EOut>
824  auto WSStream<EIn, EOut>::operator>>(const WS::Symbol& s) -> WSStream& {
825  check(WSTestSymbol(m, s.getHead().c_str()), ErrorName::WSTestSymbolError, "Cannot get symbol: \"" + s.getHead() + "\"");
826  return *this;
827  }
828 
829  template<WS::Encoding EIn, WS::Encoding EOut>
830  auto WSStream<EIn, EOut>::operator>>(WS::Symbol& s) -> WSStream& {
831  if (!s.getHead().empty()) {
832  check(WSTestSymbol(m, s.getHead().c_str()), ErrorName::WSTestSymbolError, "Cannot get symbol: \"" + s.getHead() + "\"");
833  } else {
834  const char* head {};
835  check(WSGetSymbol(m, &head), ErrorName::WSGetSymbolError, "Cannot get symbol");
836  s.setHead(head);
837  WSReleaseSymbol(m, head);
838  }
839  return *this;
840  }
841 
842  template<WS::Encoding EIn, WS::Encoding EOut>
843  auto WSStream<EIn, EOut>::operator>>(const WS::Function& f) -> WSStream& {
844  testHead(f.getHead(), f.getArgc());
845  return *this;
846  }
847 
848  template<WS::Encoding EIn, WS::Encoding EOut>
849  auto WSStream<EIn, EOut>::operator>>(WS::Function& f) -> WSStream& {
850  if (!f.getHead().empty()) {
851  if (f.getArgc() < 0) {
852  f.setArgc(testHead(f.getHead()));
853  } else {
854  testHead(f.getHead(), f.getArgc());
855  }
856  } else {
857  const char* head {};
858  int argc {};
859  check(WSGetFunction(m, &head, &argc), ErrorName::WSGetFunctionError, "Cannot get function");
860  f.setHead(head);
861  WSReleaseSymbol(m, head);
862  f.setArgc(argc);
863  }
864  return *this;
865  }
866 
867  template<WS::Encoding EIn, WS::Encoding EOut>
868  auto WSStream<EIn, EOut>::operator>>(bool& b) -> WSStream& {
869  WS::Symbol boolean;
870  *this >> boolean;
871  if (boolean.getHead() == "True") {
872  b = true;
873  } else if (boolean.getHead() == "False") {
874  b = false;
875  } else {
876  WS::Detail::throwLLUException(ErrorName::WSWrongSymbolForBool, R"(Expected "True" or "False", got )" + boolean.getHead());
877  }
878  return *this;
879  }
880 
881  template<WS::Encoding EIn, WS::Encoding EOut>
882  auto WSStream<EIn, EOut>::operator>>(mint& i) -> WSStream& {
883  i = static_cast<mint>(WS::GetScalar<wsint64>::get(m));
884  return *this;
885  }
886 
887  template<WS::Encoding EIn, WS::Encoding EOut>
888  template<WS::Encoding E, typename T>
889  auto WSStream<EIn, EOut>::operator>>(WS::GetAs<E, T> wrp) -> WSStream& {
890  WSStream<E, EOut> tmpWSS {m};
891  tmpWSS >> wrp.obj;
892  return *this;
893  }
894 
895  template<WS::Encoding EIn, WS::Encoding EOut>
896  template<typename T>
897  auto WSStream<EIn, EOut>::operator>>(WS::ArrayData<T>& a) -> WSStream& {
898  a = WS::GetArray<T>::get(m);
899  return *this;
900  }
901 
902  template<WS::Encoding EIn, WS::Encoding EOut>
903  template<typename T>
904  auto WSStream<EIn, EOut>::operator>>(WS::ListData<T>& l) -> WSStream& {
905  l = WS::GetList<T>::get(m);
906  return *this;
907  }
908 
909  template<WS::Encoding EIn, WS::Encoding EOut>
910  template<typename T>
911  auto WSStream<EIn, EOut>::operator>>(std::vector<T>& l) -> WSStream& {
912  if constexpr (WS::ScalarSupportedTypeQ<T>) {
913  auto list = WS::GetList<T>::get(m);
914  T* start = list.get();
915  auto listLen = list.get_deleter().getLength();
916  l = std::vector<T> {start, std::next(start, listLen)};
917  } else {
918  WS::List inList;
919  *this >> inList;
920  std::vector<T> res(inList.getArgc());
921  for (auto& elem : res) {
922  *this >> elem;
923  }
924  l = std::move(res);
925  }
926  return *this;
927  }
928 
929  template<WS::Encoding EIn, WS::Encoding EOut>
930  template<WS::Encoding E>
931  auto WSStream<EIn, EOut>::operator>>(WS::StringData<E>& s) -> WSStream& {
932  s = WS::String<E>::get(m);
933  return *this;
934  }
935 
936  template<WS::Encoding EIn, WS::Encoding EOut>
937  template<typename T>
938  auto WSStream<EIn, EOut>::operator>>(std::basic_string<T>& s) -> WSStream& {
939  if constexpr (WS::StringTypeQ<T>) {
940  s = WS::String<EIn>::template getString<T>(m);
941  } else {
942  static_assert(dependent_false_v<T>, "Calling operator>> with unsupported character type.");
943  }
944  return *this;
945  }
946 
947  template<WS::Encoding EIn, WS::Encoding EOut>
948  template<typename K, typename V>
949  auto WSStream<EIn, EOut>::operator>>(std::map<K, V>& map) -> WSStream& {
950  auto elemCount = testHead("Association");
951  for (auto i = 0; i < elemCount; ++i) {
952  *this >> WS::Rule;
953  K key;
954  *this >> key;
955  V value;
956  *this >> value;
957  map.emplace(std::move(key), std::move(value));
958  }
959  return *this;
960  }
961 
962  template<WS::Encoding EIn, WS::Encoding EOut>
963  template<typename T, typename>
964  auto WSStream<EIn, EOut>::operator>>(T& value) -> WSStream& {
965  if constexpr (WS::ScalarSupportedTypeQ<T>) {
966  value = WS::GetScalar<T>::get(m);
967  } else {
968  static_assert(dependent_false_v<T>, "Calling operator>> with unsupported type.");
969  }
970  return *this;
971  }
973 
974 } /* namespace LLU */
975 
976 #endif /* LLU_WSTP_WSSTREAM_HPP_ */
LLU::ErrorName::WSTestHeadError
const std::string WSTestHeadError
WSTestHead failed (wrong head or number of arguments)
LLU::WSStream::WSStream
WSStream(WSLINK mlp, const std::string &head, int argc)
Constructs new WSStream and checks whether there is a function with head head and argc arguments on t...
LLU::WSStream::operator>>
WSStream & operator>>(WS::GetAs< E, T > wrp)
Receives a value of type T.
LLU::WSStream::operator<<
WSStream & operator<<(const std::basic_string< T > &s)
Sends std::basic_string.
LLU::WSStream::operator<<
WSStream & operator<<(BidirStreamToken f)
Sends a bidirectional stream token via WSTP.
LLU::WS::Direction
Direction
Helper enum for tokens that can be sent via WSTP in both directions, e.g. WS::Null.
Definition: WSTP/Utilities.h:192
Get.h
Header file with classes related to reading data from WSTP.
LLU::WS::ArrayData
std::unique_ptr< T[], ReleaseArray< T > > ArrayData
ArrayData with of type T is a unique_ptr to an array of Ts with custom destructor.
Definition: Get.h:33
LLU::ErrorName::WSWrongSymbolForBool
const std::string WSWrongSymbolForBool
Tried to read something else than "True" or "False" as boolean.
LLU
Main namespace of LibraryLink Utilities.
Definition: Queue.h:13
Put.h
Header file with classes related to sending data through WSTP.
UtilityTypeTraits.hpp
Type traits used by WSStream to identify types supported by WSTP.
LLU::WSStream::operator<<
WSStream & operator<<(const WS::BeginExpr &expr)
Starts sending a new expression where the number of arguments is not known a priori.
LLU::ErrorName::WSNullWSLinkError
const std::string WSNullWSLinkError
Trying to create WSStream with NULL WSLINK.
LLU::WSStream::operator>>
WSStream & operator>>(WS::StringData< E > &s)
Receives a WSTP string.
LLU::WSStream
Wrapper class over WSTP with a stream-like interface.
Definition: WSTP/Utilities.h:21
LLU::WS::Function
Structure representing any function in Wolfram Language, i.e. a head plus number of arguments.
Definition: WSTP/Utilities.h:65
LLU::WS::GetAs
Utility structure used to enforce receiving given value via WSStream with encoding E.
Definition: EncodingTraits.hpp:214
LLU::WSStream::operator>>
WSStream & operator>>(WS::ListData< T > &l)
Receives a WSTP list.
LLU::WSStream::WSStream
WSStream(WSLINK mlp, int argc)
Constructs new WSStream and checks whether there is a list of argc arguments on the LinkObject waitin...
LLU::ErrorName::WSLoopbackStackSizeError
const std::string WSLoopbackStackSizeError
Loopback stack size too small to perform desired action.
LLU::WSStream::operator>>
WSStream & operator>>(WS::Symbol &s)
Receives a symbol from WSTP.
LLU::WS::Missing
Special type of a Function which corresponds to the Missing expression when exchanged with the Kernel...
Definition: WSTP/Utilities.h:136
LLU::WSStream::operator<<
WSStream & operator<<(const WS::Missing &f)
Sends a top-level expression of the form Missing["reason"].
LLU::WS::BeginExpr
Definition: WSTP/Utilities.h:272
LLU::WSStream::operator<<
WSStream & operator<<(StreamToken f)
Sends a stream token via WSTP.
LLU::WSStream::operator>>
WSStream & operator>>(std::map< K, V > &map)
Receives a std::map via WSTP.
LLU::WSStream::operator<<
WSStream & operator<<(const T(&s)[N])
Sends a character array (or a string literal)
LLU::WS::Symbol
Structure representing any symbol in Wolfram Language.
Definition: WSTP/Utilities.h:32
LLU::ErrorName::WSTransferToLoopbackError
const std::string WSTransferToLoopbackError
Something went wrong when transferring expressions from loopback link.
LLU::WSStream::operator<<
WSStream & operator<<(const WS::StringData< E > &s)
Sends a WSTP string.
LLU::WSStream::operator<<
WSStream & operator<<(mint i)
Sends a mint value.
LLU::WSStream::operator<<
WSStream & operator<<(const WS::Symbol &s)
Sends a top-level symbol via WSTP.
LLU::ErrorName::WSGetSymbolError
const std::string WSGetSymbolError
WSGetSymbol failed.
LLU::WSStream::operator>>
WSStream & operator>>(WS::Function &f)
Receives a function from WSTP.
LLU::WSStream::operator<<
WSStream & operator<<(const Container &c)
Sends any container (a class with begin(), end() and size()) as List.
Definition: WSStream.hpp:324
LLU::WSStream::operator<<
WSStream & operator<<(const std::unique_ptr< T, D > &p)
Sends an object owned by unique pointer.
LLU::WSStream::operator<<
WSStream & operator<<(bool b)
Sends a boolean value via WSTP, it is translated to True or False in Mathematica.
LLU::WSStream::sendRange
void sendRange(Iterator begin, Iterator end, const std::string &head)
Sends a range of elements as top-level expression with arbitrary head.
LLU::ErrorName::WSGetFunctionError
const std::string WSGetFunctionError
WSGetFunction failed.
LLU::WSStream::operator<<
WSStream & operator<<(const WS::Function &f)
Sends a top-level function via WSTP, function arguments should be sent immediately after.
LLU::WS::StringData
std::unique_ptr< const CharType< E >[], ReleaseString< E > > StringData
StringData with Encoding E is a unique_ptr to an array of E-encoded characters It allows you to take ...
Definition: Strings.h:43
LLU::WSStream::sendRange
void sendRange(Iterator begin, Iterator end)
Sends any range as List.
LLU::WSStream::operator>>
WSStream & operator>>(bool &b)
Receives a True or False symbol from Mathematica and converts it to bool.
LLU::WSStream::operator>>
WSStream & operator>>(WS::ArrayData< T > &a)
Receives a WSTP array.
LLU::ErrorName::WSPutFunctionError
const std::string WSPutFunctionError
WSPutFunction failed.
LLU::WS::Null
WSStream< EIn, EOut > & Null(WSStream< EIn, EOut > &ms, Direction dir)
Null is a WSStream token corresponding to a Null expression in the WolframLanguage.
Definition: WSTP/Utilities.h:261
Errors.h
Definitions of error names and error codes used across LLU.
LLU::WSStream::operator<<
WSStream & operator<<(const WS::ListData< T > &l)
Sends a WSTP list.
LLU::WSStream::operator<<
WSStream & operator<<(T value)
Sends a scalar value (int, float, double, etc) if it is supported by WSTP If you need to send value o...
LLU::WSStream::operator<<
WSStream & operator<<(const std::vector< T > &l)
Sends a std::vector via WSTP, it is interpreted as a List in Mathematica.
LLU::WSStream::operator>>
WSStream & operator>>(std::basic_string< T > &s)
Receives std::basic_string.
LLU::WSStream::operator>>
WSStream & operator>>(std::vector< T > &l)
Receives a List from WSTP and assigns it to std::vector.
LLU::WSStream::operator<<
WSStream & operator<<(const WS::ArrayData< T > &a)
Sends a WSTP array.
LLU::WSStream::operator<<
WSStream & operator<<(const std::map< K, V > &map)
Sends a std::map via WSTP, it is translated to an Association in Mathematica.
LLU::WS::DropExpr
Definition: WSTP/Utilities.h:284
Utilities.h
Header file with miscellaneous utilities used throughout the WSTP-related part of LibraryLinkUtilitie...
LLU::WSStream::~WSStream
~WSStream()=default
Default destructor.
LLU::WS::ListData
std::unique_ptr< T[], ReleaseList< T > > ListData
ListData with of type T is a unique_ptr to an array of Ts with custom destructor.
Definition: Get.h:27
Strings.h
Definitions of multiple structures and type aliases related to string handling in WSTP.
LLU::WSStream::operator>>
WSStream & operator>>(const WS::Symbol &s)
Receives a symbol from WSTP.
LLU::WS::EndExpr
Definition: WSTP/Utilities.h:290
LLU::WSStream::operator<<
WSStream & operator<<(const WS::PutAs< E, T > &wrp)
Sends all strings within a given object using specified character encoding.
LLU::WSStream::operator<<
WSStream & operator<<(const WS::EndExpr &expr)
Ends current expression that was initiated with BeginExpr, prepends the head from BeginExpr and sends...
LLU::WS::Rule
WSStream< EIn, EOut > & Rule(WSStream< EIn, EOut > &ms, Direction dir)
Rule is a WSStream token corresponding to a Rule expression in the WolframLanguage.
Definition: WSTP/Utilities.h:245
LLU::WSStream::operator>>
WSStream & operator>>(BidirStreamToken f)
Receives a bidirectional stream token via WSTP.
LLU::WSStream::operator<<
WSStream & operator<<(const char *s)
Sends a C-string.
LLU::WSStream::BidirStreamToken
WSStream &(*)(WSStream &, WS::Direction) BidirStreamToken
Type of elements that can be either sent or received via WSTP with no arguments, for example WS::Rule...
Definition: WSStream.hpp:106
LLU::WS::PutAs
Utility structure used to enforce sending given value with encoding E via WSStream.
Definition: EncodingTraits.hpp:150
LLU::WSStream::StreamToken
WSStream &(*)(WSStream &) StreamToken
Type of elements that can be sent via WSTP with no arguments, for example WS::Flush.
Definition: WSStream.hpp:103
LLU::WSStream::LoopbackData
std::pair< std::string, WSLINK > LoopbackData
Type of data stored on the stack to facilitate sending expressions of a priori unknown length.
Definition: WSStream.hpp:109
LLU::WSStream::operator<<
WSStream & operator<<(const WS::DropExpr &expr)
Drops current expression that was initiated with BeginExpr.
LLU::ErrorName::WSTestSymbolError
const std::string WSTestSymbolError
WSTestSymbol failed (different symbol on the link than expected)
LLU::WSStream::get
WSLINK & get() noexcept
Returns a reference to underlying low-level WSTP handle.
Definition: WSStream.hpp:76
LLU::WSStream::WSStream
WSStream(WSLINK mlp)
Constructs new WSStream.
LLU::WSStream::operator>>
WSStream & operator>>(mint &i)
Receives a mint value.
Utilities.hpp
Short but generally useful functions.
LLU::WSStream::operator>>
WSStream & operator>>(const WS::Function &f)
Receives a function from WSTP.
LLU::WSStream::operator>>
WSStream & operator>>(T &value)
Receives a scalar value (int, float, double, etc) if it is supported by WSTP If you need to receive v...
LLU::ErrorName::WSPutSymbolError
const std::string WSPutSymbolError
WSPutSymbol failed.