コード例 #1
0
ファイル: main.cpp プロジェクト: matsuokah/actor_sample
int main()
{
  auto pool = std::make_shared<thread_pool>(4);

  auto a = std::make_shared<sample::sample_actor>(std::move(pool));
  auto t1 = std::thread([a]()
      {
        for (int i = 0; i < 1000; i++) 
        {
          std::stringstream ss;
          ss << "thread 1: " << i;

          auto fut = a->send_message<sample::message, sample::result>(std::move(sample::message{ss.str()}));
          fut.wait();

          auto res = fut.get();
          if (res.is_nothing())
          {
            std::cout << "result is nothing, continue..." << std::endl;
            continue;
          }

          std::cout << res.get()->str << std::endl;
        }
      });

  auto t2 = std::thread([a]()
      {
        for (int i = 0; i < 1000; i++) 
        {
          std::stringstream ss;
          ss << "thread 2: " << i;

          auto fut = a->send_message<sample::message, sample::result>(std::move(sample::message{ss.str()}));

          fut.wait();
          auto res = fut.get();
          if (res.is_nothing())
          {
            std::cout << "result is nothing, continue..." << std::endl;
            continue;
          }

          std::cout << res.get()->str << std::endl;
        }
      });

  t1.join();
  t2.join();

  t1.detach();
  t2.detach();
  return 0;
}
コード例 #2
0
ファイル: serializer.cpp プロジェクト: lowkey42/teamproject
	void load(sf2::JsonDeserializer& s, Entity& e) {
		static_assert(sf2::details::has_load<format::Json_reader,details::Component_base>::value, "missing load");
		s.read_lambda([&](const auto& key){
			auto mb_comp = e.manager().find_comp_info(key);

			if(mb_comp.is_nothing()) {
				DEBUG("Skipped unknown component "<<key);
				s.skip_obj();
				return true;

			}

			auto& comp = mb_comp.get_or_throw();
			auto& ecs_deserializer = static_cast<EcsDeserializer&>(s);

			if(ecs_deserializer.filter && !ecs_deserializer.filter(comp.type)) {
				DEBUG("Skipped filtered component "<<key);
				s.skip_obj();
				return true;
			}

			auto comp_ptr = comp.get(e);
			if(!comp_ptr) {
				comp.add(e);
				comp_ptr = comp.get(e);
			}

			s.read_value(*comp_ptr);

			return true;
		});
	}
コード例 #3
0
ファイル: method.c プロジェクト: tundra/neutrino
// Returns true if the given signature could possibly match an invocation where
// the given tag maps to the given value.
static bool can_match_eq(value_t signature, value_t tag, value_t value) {
  int64_t paramc = get_signature_parameter_count(signature);
  // First look for a matching parameter in the signature.
  value_t match = nothing();
  for (int64_t i = 0; i < paramc; i++) {
    value_t param = get_signature_parameter_at(signature, i);
    value_t tags = get_parameter_tags(param);
    if (in_array(tags, tag)) {
      match = param;
      break;
    }
  }
  if (is_nothing(match)) {
    // There was no matching parameter so this can only match if the signature
    // permits it as an extra argument.
    return get_signature_allow_extra(signature);
  } else {
    value_t guard = get_parameter_guard(match);
    if (get_guard_type(guard) == gtEq) {
      value_t eq_value = get_guard_value(guard);
      return value_identity_compare(value, eq_value);
    } else {
      return true;
    }
  }
}
コード例 #4
0
ファイル: music.cpp プロジェクト: lowkey42/teamproject
	Music::Music(asset::istream stream) throw(Music_loading_failed) :
	    _handle(nullptr, Mix_FreeMusic), _stream(std::make_unique<asset::istream>(std::move(stream))){

		auto id = _stream->aid();

#ifndef EMSCRIPTEN
		SDL_RWops *rwops = SDL_AllocRW();
		INVARIANT(rwops, "SDL_AllocRW failed");

		rwops->seek = istream_seek;
		rwops->read = istream_read;
		rwops->write = NULL;
		rwops->close = istream_close;
		rwops->hidden.unknown.data1 = _stream.get();

		_handle.reset(Mix_LoadMUS_RW(rwops, 1));

#else
		auto location = _stream->physical_location();
		_stream.reset();

		if(location.is_nothing())
			return;

		_handle.reset(Mix_LoadMUS(location.get_or_throw().c_str()));
#endif

		if(!_handle){
			WARN("Mix_LoadMUS_RW ("<<id.str()<<") failed: " << Mix_GetError());
		}

	}
コード例 #5
0
ファイル: interp.c プロジェクト: plesner/neutrino
// Gets the code from a method object, compiling the method if necessary.
static value_t ensure_method_code(runtime_t *runtime, value_t method) {
    value_t code = get_method_code(method);
    if (is_nothing(code)) {
        TRY_SET(code, compile_method(runtime, method));
        set_method_code(method, code);
    }
    return code;
}
コード例 #6
0
ファイル: maybe.c プロジェクト: SiChiTong/opic
void Maybe_f_fmap(OPObject* _self, OPObject* _next, f_fmap_callback cb)
{
  Maybe* self = (Maybe*) _self;
  Maybe* next = (Maybe*) _next;
  if (is_nothing(self) && self != next) {
    nothing(next);
  }
  cb(self->data, &next->data);
}
コード例 #7
0
int64 getMicroSecZeroInt64(const AbstractQoreNode* a) {
   if (is_nothing(a))
      return 0;

   if (a->getType() == NT_DATE)
      return (reinterpret_cast<const DateTimeNode*>(a)->getRelativeMicroseconds());

   return a->getAsBigInt();
}
コード例 #8
0
ファイル: maybe.c プロジェクト: SiChiTong/opic
void Maybe_m_bind(OPObject* _self, m_bind_callback cb, OPObject* _next)
{
  Maybe* self = (Maybe*) _self;
  Maybe* next = (Maybe*) _next;
  if (is_nothing(self) && self != next) {
    nothing(next);
  }
  cb(self->data, _next);
}
コード例 #9
0
int64 getMsMinusOneBigInt(const AbstractQoreNode* a) {
   if (is_nothing(a))
      return -1;

   if (a->getType() == NT_DATE)
      return reinterpret_cast<const DateTimeNode*>(a)->getRelativeMilliseconds();

   return a->getAsBigInt();
}
コード例 #10
0
// for getting relative time values or integer values
int getSecMinusOneInt(const AbstractQoreNode* a) {
   if (is_nothing(a))
      return -1;

   if (a->getType() == NT_DATE)
      return (int)(reinterpret_cast<const DateTimeNode*>(a)->getRelativeSeconds());

   return a->getAsInt();
}
コード例 #11
0
int getMsZeroInt(const AbstractQoreNode* a) {
   if (is_nothing(a))
      return 0;

   if (a->getType() == NT_DATE)
      return (int)(reinterpret_cast<const DateTimeNode*>(a)->getRelativeMilliseconds());

   return a->getAsInt();
}
コード例 #12
0
ファイル: process.c プロジェクト: plesner/neutrino
value_t stack_validate(value_t self) {
  VALIDATE_FAMILY(ofStack, self);
  VALIDATE_FAMILY(ofStackPiece, get_stack_top_piece(self));
  value_t current = get_stack_top_piece(self);
  while (!is_nothing(current)) {
    value_t stack = get_stack_piece_stack(current);
    VALIDATE(is_same_value(stack, self));
    current = get_stack_piece_previous(current);
  }
  return success();
}
コード例 #13
0
ファイル: pairs.hpp プロジェクト: offa/FunctionalPlus
maybe<TOut> first_match_by(F f, const ContainerIn1& xs, const ContainerIn2& ys)
{
    const auto maybe_idx = first_match_idx_by(f, xs, ys);
    if (is_nothing(maybe_idx))
    {
        return nothing<TOut>();
    }
    else
    {
        const auto idx = maybe_idx.unsafe_get_just();
        return just(std::make_pair(
            elem_at_idx(idx, xs),
            elem_at_idx(idx, ys)));
    }
}
コード例 #14
0
ファイル: method.c プロジェクト: tundra/neutrino
value_t get_or_create_methodspace_selector_slice(runtime_t *runtime, value_t self,
    value_t selector) {
  value_t cache_ptr = get_methodspace_cache_ptr(self);
  value_t cache = get_freeze_cheat_value(cache_ptr);
  // Create the cache if it doesn't exist.
  if (is_nothing(cache)) {
    TRY_SET(cache, new_heap_id_hash_map(runtime, 128));
    set_freeze_cheat_value(cache_ptr, cache);
  }
  // Create the selector-specific cache if it doesn't exits.
  value_t slice = get_id_hash_map_at(cache, selector);
  if (in_condition_cause(ccNotFound, slice)) {
    TRY_SET(slice, create_methodspace_selector_slice(runtime, self, selector));
    TRY(set_id_hash_map_at(runtime, cache, selector, slice));
  }
  return slice;
}
コード例 #15
0
ファイル: bind.c プロジェクト: plesner/neutrino
// Binds an individual module fragment.
static value_t bind_module_fragment(binding_context_t *context,
    value_t entry, value_t bound_fragment) {
  CHECK_FAMILY(ofModuleFragment, bound_fragment);
  value_t unbound_fragment = get_fragment_entry_fragment(entry);
  value_t imports = get_fragment_entry_imports(entry);
  if (!is_nothing(unbound_fragment)) {
    // This is a real fragment so we have to apply the entries.
    CHECK_FAMILY(ofUnboundModuleFragment, unbound_fragment);
    CHECK_EQ("fragment already bound", feUnbound,
        get_module_fragment_epoch(bound_fragment));
    set_module_fragment_epoch(bound_fragment, feBinding);
    TRY(bind_module_fragment_imports(context, imports, bound_fragment));
    TRY(apply_module_fragment_elements(context, unbound_fragment, bound_fragment));
  }
  set_module_fragment_epoch(bound_fragment, feComplete);
  return success();
}
コード例 #16
0
ファイル: method.c プロジェクト: tundra/neutrino
static value_t create_methodspace_selector_slice(runtime_t *runtime, value_t self,
    value_t selector) {
  TRY_DEF(result, new_heap_signature_map(runtime));
  value_t current = self;
  while (!is_nothing(current)) {
    value_t methods = get_methodspace_methods(current);
    value_t entries = get_signature_map_entries(methods);
    for (int64_t i = 0; i < get_pair_array_buffer_length(entries); i++) {
      value_t signature = get_pair_array_buffer_first_at(entries, i);
      if (can_match_eq(signature, ROOT(runtime, selector_key), selector)) {
        value_t method = get_pair_array_buffer_second_at(entries, i);
        TRY(add_to_signature_map(runtime, result, signature, method));
      }
    }
    current = get_methodspace_parent(current);
  }
  return result;
}
コード例 #17
0
java::lang::Object *toJava(const AbstractQoreNode *n, ExceptionSink *xsink) {
   if (is_nothing(n))
      return 0;

   switch (n->getType()) {
      case NT_STRING:
         return toJava(*(reinterpret_cast<const QoreStringNode *>(n)), xsink);
      case NT_INT: {
         int64 v = reinterpret_cast<const QoreBigIntNode *>(n)->val;
         if ((v & 0xff) == v)
            return toJava((jbyte)v);
         if ((v & 0xffff) == v)
            return toJava((jshort)v);
         if ((v & 0xffffffff) == v)
            return toJava((jint)v);
         return toJava((jlong)v);
      }
      case NT_BOOLEAN:
         return toJava((jboolean)reinterpret_cast<const QoreBoolNode *>(n)->getValue());
      case NT_FLOAT:
         return toJava((jdouble)reinterpret_cast<const QoreFloatNode *>(n)->f);
      case NT_OBJECT: {
         const QoreObject *o = reinterpret_cast<const QoreObject *>(n);
         // get java object
         PrivateDataRefHolder<QoreJavaPrivateData> jo(o, CID_OBJECT, xsink);
         if (!jo) {
            if (!*xsink)
               xsink->raiseException("JAVA-UNSUPPORTED-TYPE", "cannot convert from Qore class '%s' to a Java value; '%s' does not inherit java::lang::Object", o->getClassName(), o->getClassName());
            return 0;
         }
         return jo->getObject();
      }
   }

   xsink->raiseException("JAVA-UNSUPPORTED-TYPE", "cannot convert from Qore '%s' to a Java value", get_type_name(n));

   return 0;
}
コード例 #18
0
ファイル: bind.c プロジェクト: plesner/neutrino
// Add synthetic fragment entries corresponding to imported fragments where
// there is no real fragment to import the fragment into.
static value_t build_synthetic_fragment_entries(binding_context_t *context) {
  // Keep adding synthetic modules as long as changes are being made to the
  // map. We'll scan through the fragments currently in the map, then scan
  // through their imports, and for each check that the fragment that should
  // receive the import exists. If it doesn't it is created.
  loop: do {
    id_hash_map_iter_t module_iter;
    id_hash_map_iter_init(&module_iter, context->fragment_entry_map);
    while (id_hash_map_iter_advance(&module_iter)) {
      value_t module_path;
      value_t module_fragments;
      // Scan through the fragments.
      id_hash_map_iter_get_current(&module_iter, &module_path, &module_fragments);
      id_hash_map_iter_t fragment_iter;
      id_hash_map_iter_init(&fragment_iter, module_fragments);
      while (id_hash_map_iter_advance(&fragment_iter)) {
        value_t stage;
        value_t entry;
        id_hash_map_iter_get_current(&fragment_iter, &stage, &entry);
        value_t unbound_fragment = get_fragment_entry_fragment(entry);
        // If there is no fragment associated with this entry it is synthetic
        // and hence we're done.
        if (is_nothing(unbound_fragment))
          continue;
        // Scan through the fragment's imports and ensure that their import
        // targets have been created.
        value_t imports = get_fragment_entry_imports(entry);
        for (size_t i = 0; i < get_array_buffer_length(imports); i++) {
          value_t import = get_array_buffer_at(imports, i);
          value_t import_fragment_stage = get_identifier_stage(import);
          if (!value_identity_compare(import_fragment_stage, present_stage()))
            // We'll record past imports but ignore them for the purposes of
            // closing the import map since they're redundant.
            continue;
          value_t import_module_path = get_identifier_path(import);
          value_t import_module = get_id_hash_map_at(context->fragment_entry_map,
              import_module_path);
          // Scan through the fragments of the imported module.
          id_hash_map_iter_t imported_fragment_iter;
          id_hash_map_iter_init(&imported_fragment_iter, import_module);
          bool has_changed_anything = false;
          while (id_hash_map_iter_advance(&imported_fragment_iter)) {
            value_t import_stage;
            value_t import_entry;
            id_hash_map_iter_get_current(&imported_fragment_iter,
                &import_stage, &import_entry);
            value_t target_stage = add_stage_offsets(import_stage, stage);
            // Ensure that there is a target entry to add the import to. If it
            // already exists this is a no-op, if it doesn't a synthetic entry
            // is created.
            TRY_DEF(target_entry, binding_context_ensure_fragment_entry(
                context, target_stage, module_path, nothing(),
                &has_changed_anything));
           value_t target_imports = get_fragment_entry_imports(target_entry);
           value_t import_ident = get_fragment_entry_identifier(import_entry);
            if (!in_array_buffer(target_imports, import_ident)) {
              has_changed_anything = true;
              TRY(add_to_array_buffer(get_ambience_runtime(context->ambience),
                  target_imports, import_ident));
            }
          }
          // If any changes were made we have to start over.
          if (has_changed_anything)
            goto loop;
        }
      }
    }
  } while (false);
  return success();
}
コード例 #19
0
// FIXME: use ct_setparam to avoid copying data
void command::set_params(sybase_query &query, const QoreListNode *args, ExceptionSink *xsink) {
   unsigned nparams = query.param_list.size();

   for (unsigned i = 0; i < nparams; ++i) {
      if (query.param_list[i] == 'd')
	 continue;

      const AbstractQoreNode *val = args ? args->retrieve_entry(i) : NULL;

      CS_DATAFMT datafmt;
      memset(&datafmt, 0, sizeof(datafmt));
      datafmt.status = CS_INPUTVALUE;
      datafmt.namelen = CS_NULLTERM;
      sprintf(datafmt.name, "@par%d", int(i + 1));
      datafmt.maxlength = CS_UNUSED;
      datafmt.count = 1;

      CS_RETCODE err = CS_FAIL;

      if (!val || is_null(val) || is_nothing(val)) {
#ifdef FREETDS
	 // it seems to be necessary to specify a type like
	 // this to get a null value to be bound with freetds
	 datafmt.datatype = CS_CHAR_TYPE;
	 datafmt.format = CS_FMT_NULLTERM;
	 datafmt.maxlength = 1;
#endif
	 // SQL NULL value
	 err = ct_param(m_cmd, &datafmt, 0, CS_UNUSED, -1);
	 if (err != CS_SUCCEED) {
	    m_conn.do_exception(xsink, "DBI:SYBASE:EXEC-ERROR",
				"ct_param() for 'null' failed for parameter %u with error %d",
				i, (int)err);
	    return;
	 }
	 continue;
      }

      qore_type_t ntype = val ? val->getType() : 0;

      switch (ntype) {
	 case NT_STRING: {
	    const QoreStringNode *str = reinterpret_cast<const QoreStringNode *>(val);
	    // ensure we bind with the proper encoding for the connection
	    TempEncodingHelper s(str, m_conn.getEncoding(), xsink);
	    if (!s) throw ss::Error("DBI:SYBASE:EXEC-ERROR", "encoding");

	    int slen = s->strlen();
	    datafmt.datatype = CS_CHAR_TYPE;
	    datafmt.format = CS_FMT_NULLTERM;
	    // NOTE: setting large sizes here like 2GB works for sybase ctlib,
	    // not for freetds
	    datafmt.maxlength = slen + 1;
	    err = ct_param(m_cmd, &datafmt, (CS_VOID*)s->getBuffer(), slen, 0);
	    break;
	 }

	 case NT_NUMBER: {
	    QoreStringValueHelper vh(val);
	    int slen = vh->strlen();
	    datafmt.datatype = CS_CHAR_TYPE;
	    datafmt.format = CS_FMT_NULLTERM;
	    datafmt.maxlength = slen + 1;
	    err = ct_param(m_cmd, &datafmt, (CS_VOID *)vh->getBuffer(), slen, 0);
	    break;
	 }

	 case NT_DATE: {
	    const DateTimeNode *date = reinterpret_cast<const DateTimeNode *>(val);
	    CS_DATETIME dt;
	    ss::Conversions conv;
	    if (conv.DateTime_to_DATETIME(date, dt, xsink))
	       throw ss::Error("DBI:SYBASE:EXEC-ERROR", "can't convert date");

	    datafmt.datatype = CS_DATETIME_TYPE;
	    err = ct_param(m_cmd, &datafmt, &dt, sizeof(dt), 0);
	    break;
	 }

	 case NT_INT: {
#ifdef CS_BIGINT_TYPE
	    datafmt.datatype = CS_BIGINT_TYPE;
	    err = ct_param(m_cmd, &datafmt, &(const_cast<QoreBigIntNode *>(reinterpret_cast<const QoreBigIntNode *>(val))->val), sizeof(int64), 0);
#else
	    int64 ival = reinterpret_cast<const QoreBigIntNode *>(val)->val;
	    // if it's a 32-bit integer, bind as integer
	    if (ival <= 2147483647 && ival >= -2147483647) {
	       datafmt.datatype = CS_INT_TYPE;
	       CS_INT vint = ival;
	       err = ct_param(m_cmd, &datafmt, &vint, sizeof(CS_INT), 0);
	    }
	    else { // bind as float
	       CS_FLOAT fval = ival;
	       datafmt.datatype = CS_FLOAT_TYPE;
	       err = ct_param(m_cmd, &datafmt, &fval, sizeof(CS_FLOAT), 0);
	    }
#endif
	    break;
	 }

	 case NT_BOOLEAN: {
	    // Seems mssql doesn't like  CS_BIT_TYPE for some reason.
	    // Replacing by CS_INT_TYPE helps
	    //
	    // The "BIT" code is supposed to be like this:
	    // datafmt.datatype = CS_BIT_TYPE;
	    // err = ct_param(m_cmd, &datafmt, &bval, sizeof(bval), 0);
	    // ... but it doesn't work

	    CS_BIT bval = reinterpret_cast<const QoreBoolNode *>(val)->getValue();
	    datafmt.datatype = CS_INT_TYPE;
	    int64 ival = bval ? 1 : 0;
	    err = ct_param(m_cmd, &datafmt, &ival, sizeof(ival), 0);
	    break;
	 }

	 case NT_FLOAT: {
	    CS_FLOAT fval = reinterpret_cast<const QoreFloatNode *>(val)->f;
	    datafmt.datatype = CS_FLOAT_TYPE;
	    err = ct_param(m_cmd, &datafmt, &fval, sizeof(CS_FLOAT), 0);
	    break;
	 }

	 case NT_BINARY: {
	    const BinaryNode *b = reinterpret_cast<const BinaryNode *>(val);
	    datafmt.datatype = CS_BINARY_TYPE;
	    datafmt.maxlength = b->size();
	    datafmt.count = 1;
	    err = ct_param(m_cmd, &datafmt, (void *)b->getPtr(), b->size(), 0);
	    break;
	 }

	 default:
	    m_conn.do_exception(xsink, "DBI:SYBASE:BIND-ERROR",
				"do not know how to bind values of type '%s'",
				val->getTypeName());
	    return;
      } // switch(ntype)

      if (err != CS_SUCCEED) {
	 m_conn.do_exception(xsink, "DBI:SYBASE:EXEC-ERROR",
			     "ct_param() for binary parameter %u failed with error",
			     i, (int)err);
      }
   }
}
コード例 #20
0
ファイル: QoreValue.cpp プロジェクト: temnoregg/qore
bool QoreValue::isNullOrNothing() const {
   return type == QV_Node && (is_nothing(v.n) || is_null(v.n));
}
コード例 #21
0
QoreHashNode* qore_httpclient_priv::send_internal(ExceptionSink* xsink, const char* mname, const char* meth, const char* mpath, const QoreHashNode* headers, const void* data, unsigned size, const ResolvedCallReferenceNode* send_callback, bool getbody, QoreHashNode* info, int timeout_ms, const ResolvedCallReferenceNode* recv_callback, QoreObject* obj) {
   assert(!(data && send_callback));

   // check if method is valid
   method_map_t::const_iterator i = method_map.find(meth);
   if (i == method_map.end()) {
       i = additional_methods_map.find(meth);
       if (i == additional_methods_map.end()) {
          xsink->raiseException("HTTP-CLIENT-METHOD-ERROR", "HTTP method (%s) not recognized.", meth);
          return 0;
       }
   }

   // make sure the capitalized version is used
   meth = i->first.c_str();
   bool bodyp = i->second;

   // use the default timeout value if a zero value is given in the call
   if (!timeout_ms)
      timeout_ms = timeout;

   SafeLocker sl(msock->m);
   Queue* cb_queue = msock->socket->getQueue();

   ReferenceHolder<QoreHashNode> nh(new QoreHashNode, xsink);
   bool keep_alive = true;

   bool transfer_encoding = false;

   if (headers) {
      ConstHashIterator hi(headers);
      while (hi.next()) {
	 // if one of the mandatory headers is found, then ignore it
	 strcase_set_t::iterator si = header_ignore.find(hi.getKey());
	 if (si != header_ignore.end())
	    continue;

	 // otherwise set the value in the hash
	 const AbstractQoreNode* n = hi.getValue();
	 if (!is_nothing(n)) {
	    if (!strcasecmp(hi.getKey(), "transfer-encoding"))
	       transfer_encoding = true;

	    nh->setKeyValue(hi.getKey(), n->refSelf(), xsink);

	    if (!strcasecmp(hi.getKey(), "connection") || (proxy_connection.has_url() && !strcasecmp(hi.getKey(), "proxy-connection"))) {
	       const char* conn = get_string_header(xsink, **nh, hi.getKey(), true);
	       if (*xsink) {
		  disconnect_unlocked();
		  return 0;
	       }
	       if (conn && !strcasecmp(conn, "close"))
		  keep_alive = false;
	    }
	 }
      }
   }

   // add default headers if they weren't overridden
   for (header_map_t::const_iterator hdri = default_headers.begin(), e = default_headers.end(); hdri != e; ++hdri) {
      // look in original headers to see if the key was already given
      if (headers) {
	 bool skip = false;
	 ConstHashIterator hi(headers);
	 while (hi.next()) {
	    if (!strcasecmp(hi.getKey(), hdri->first.c_str())) {
	       skip = true;
	       break;
	    }
	 }
	 if (skip)
	    continue;
      }
      // if there is no message body then do not send the "content-type" header
      if (!data && !send_callback && !strcmp(hdri->first.c_str(), "Content-Type"))
	 continue;
      nh->setKeyValue(hdri->first.c_str(), new QoreStringNode(hdri->second.c_str()), xsink);
   }

   // set Transfer-Encoding: chunked if used with a send callback
   if (send_callback && !transfer_encoding)
      nh->setKeyValue("Transfer-Encoding", new QoreStringNode("chunked"), xsink);

   if (!connection.username.empty()) {
      // check for "Authorization" header
      bool auth_found = false;
      if (headers) {
	 ConstHashIterator hi(headers);
	 while (hi.next()) {
	    if (!strcasecmp(hi.getKey(), "Authorization")) {
	       auth_found = true;
	       break;
	    }
	 }
      }

      if (!auth_found) {
	 QoreString tmp;
	 tmp.sprintf("%s:%s", connection.username.c_str(), connection.password.c_str());
	 QoreStringNode* auth_str = new QoreStringNode("Basic ");
	 auth_str->concatBase64(&tmp);
	 nh->setKeyValue("Authorization", auth_str, xsink);
      }
   }

   // save original HTTP method in case we have to issue a CONNECT request to a proxy for an HTTPS connection
   const char* meth_orig = meth;

   bool use_proxy_connect = false;
   const char* proxy_path = 0;
   ReferenceHolder<QoreHashNode> proxy_headers(xsink);
   QoreString hostport;
   if (!proxy_connected && proxy_connection.has_url()) {
      // use CONNECT if we need to make an HTTPS connection from the proxy
      if (!proxy_connection.ssl && connection.ssl) {
	 meth = "CONNECT";
	 use_proxy_connect = true;
	 hostport.concat(connection.host);
	 if (connection.port)
	    hostport.sprintf(":%d", connection.port);
	 proxy_path = hostport.getBuffer();
	 proxy_headers = new QoreHashNode;
	 proxy_headers->setKeyValue("Host", new QoreStringNode(hostport), xsink);

	 addProxyAuthorization(headers, **proxy_headers, xsink);
      }
      else
	 addProxyAuthorization(headers, **nh, xsink);
   }

   bool host_override = headers ? (bool)headers->getKeyValue("Host") : false;

   int code;
   ReferenceHolder<QoreHashNode> ans(xsink);
   int redirect_count = 0;
   const char* location = 0;

   // flag for aborted chunked sends
   bool send_aborted = false;

   while (true) {
      // set host field automatically if not overridden
      if (!host_override)
	 nh->setKeyValue("Host", getHostHeaderValue(), xsink);

      if (info) {
	 info->setKeyValue("headers", nh->copy(), xsink);
	 if (*xsink)
	    return 0;
      }

      //printd(5, "qore_httpclient_priv::send_internal() meth=%s proxy_path=%s mpath=%s upc=%d\n", meth, proxy_path ? proxy_path : "n/a", mpath, use_proxy_connect);
      // send HTTP message and get response header
      if (use_proxy_connect)
	 ans = sendMessageAndGetResponse(meth, proxy_path, *(*proxy_headers), 0, 0, 0, info, true, timeout_ms, code, send_aborted, xsink);
      else
	 ans = sendMessageAndGetResponse(meth, mpath, *(*nh), data, size, send_callback, info, false, timeout_ms, code, send_aborted, xsink);
      if (!ans)
	 return 0;

      if (info) {
	 info->setKeyValue("response-headers", ans->refSelf(), xsink);
	 if (*xsink)
	    return 0;
      }

      if (code >= 300 && code < 400) {
	 disconnect_unlocked();

	 host_override = false;
	 const QoreStringNode* mess = reinterpret_cast<QoreStringNode*>(ans->getKeyValue("status_message"));

	 const QoreStringNode* loc = get_string_header_node(xsink, **ans, "location");
	 if (*xsink)
	    return 0;
	 const char* location = loc && !loc->empty() ? loc->getBuffer() : 0;
	 if (!location) {
	    sl.unlock();
	    const char* msg = mess ? mess->getBuffer() : "<no message>";
	    xsink->raiseException("HTTP-CLIENT-REDIRECT-ERROR", "no redirect location given for status code %d: message: '%s'", code, msg);
	    return 0;
	 }

	 if (cb_queue)
	    do_redirect_event(cb_queue, msock->socket->getObjectIDForEvents(), loc, mess);

	 if (++redirect_count > max_redirects)
	    break;

	 if (set_url_unlocked(location, xsink)) {
	    sl.unlock();
	    const char* msg = mess ? mess->getBuffer() : "<no message>";
	    xsink->raiseException("HTTP-CLIENT-REDIRECT-ERROR", "exception occurred while setting URL for new location '%s' (code %d: message: '%s')", location, code, msg);
	    return 0;
	 }

	 // set redirect info in info hash if present
	 if (info) {
	    QoreString tmp;
	    tmp.sprintf("redirect-%d", redirect_count);
	    info->setKeyValue(tmp.getBuffer(), loc->refSelf(), xsink);
	    if (*xsink)
	       return 0;

	    tmp.clear();
	    tmp.sprintf("redirect-message-%d", redirect_count);
	    info->setKeyValue(tmp.getBuffer(), mess ? mess->refSelf() : 0, xsink);
	 }

	 // FIXME: reset send callback and send_aborted here

	 // set mpath to NULL so that the new path will be taken
	 mpath = 0;
	 continue;
      }
      else if (use_proxy_connect) {
	 meth = meth_orig;
	 use_proxy_connect = false;
	 proxy_path = 0;
	 if (msock->socket->upgradeClientToSSL(0, 0, xsink)) {
	    disconnect_unlocked();
	    return 0;
	 }
	 proxy_connected = true;

	 // remove "Proxy-Authorization" header
	 nh->removeKey("Proxy-Authorization", xsink);
	 if (*xsink)
	    return 0;

	 // try again as if we are talking directly to the client
	 continue;
      }

      break;
   }

   if (code >= 300 && code < 400) {
      sl.unlock();
      const char* mess = get_string_header(xsink, **ans, "status_message");
      if (!mess)
	 mess = "<no message>";
      if (!location)
	 location = "<no location>";
      xsink->raiseException("HTTP-CLIENT-MAXIMUM-REDIRECTS-EXCEEDED", "maximum redirections (%d) exceeded; redirect code %d to '%s' ignored (message: '%s')", max_redirects, code, location, mess);
      return 0;
   }

   // process content-type
   const QoreStringNode* v = get_string_header_node(xsink, **ans, "content-type");
   if (*xsink) {
      disconnect_unlocked();
      return 0;
   }
   //ans->getKeyValue("content-type");   

   // see if there is a character set specification in the content-type header
   if (v) {
      // save original content-type header before processing
      ans->setKeyValue("_qore_orig_content_type", v->refSelf(), xsink);

      const char* str = v->getBuffer();
      const char* p = strstr(str, "charset=");
      if (p && (p == str || *(p - 1) == ';' || *(p - 1) == ' ')) {
	 // move p to start of encoding
	 const char* c = p + 8;
	 char quote = '\0';
	 if (*c == '\'' || *c == '"') {
	    quote = *c;
	    ++c;
	 }
	 QoreString enc;
	 while (*c && *c != ';' && *c != ' ' && *c != quote)
	    enc.concat(*(c++));
	 
	 if (quote && *c == quote)
	    ++c;

	 printd(5, "QoreHttpClientObject::send_intern() setting encoding to '%s' from content-type header: '%s' (cs=%p c=%p %d)\n", enc.getBuffer(), str, p + 8, c);

	 // set new encoding
	 msock->socket->setEncoding(QEM.findCreate(&enc));
	 // strip from content-type
	 QoreStringNode* nc = new QoreStringNode();
	 // skip any spaces before the charset=
	 while (p != str && (*(p - 1) == ' ' || *(p - 1) == ';'))
	    p--;
	 if (p != str)
	    nc->concat(str, p - str);
	 if (*c)
	    nc->concat(c);
	 ans->setKeyValue("content-type", nc, xsink);
	 str = nc->getBuffer();
      }
      // split into a list if ";" characters are present
      p = strchr(str, ';');
      if (p) {
	 bool multipart = false;
	 QoreListNode* l = new QoreListNode();
	 do {
	    // skip whitespace
	    while (*str == ' ') str++;
	    if (str != p) {
	       int len = p - str;
	       check_headers(str, len, multipart, *(*ans), msock->socket->getEncoding(), xsink);
	       l->push(new QoreStringNode(str, len, msock->socket->getEncoding()));
	    }
	    str = p + 1;
	 } while ((p = strchr(str, ';')));
	 // skip whitespace
	 while (*str == ' ') str++;
	 // add last field
	 if (*str) {
	    check_headers(str, strlen(str), multipart, *(*ans), msock->socket->getEncoding(), xsink);
	    l->push(new QoreStringNode(str, msock->socket->getEncoding()));
	 }
	 ans->setKeyValue("content-type", l, xsink);
      }
   }

   // send headers to recv_callback
   if (recv_callback && msock->socket->priv->runHeaderCallback(xsink, mname, *recv_callback, &msock->m, *ans, send_aborted, obj))
      return 0;

   AbstractQoreNode* body = 0;
   const char* content_encoding = 0;

   // do not read any message body for messages that cannot have one
   // rfc 2616 4.4 p1 (http://tools.ietf.org/html/rfc2616#section-4.4)
   /*
     1.Any response message which "MUST NOT" include a message-body (such
     as the 1xx, 204, and 304 responses and any response to a HEAD
     request) is always terminated by the first empty line after the
     header fields, regardless of the entity-header fields present in
     the message.
    */
   //printd(5, "qore_httpclient_priv::send_internal() this: %p bodyp: %d code: %d\n", this, bodyp, code);

   qore_uncompress_to_string_t dec = 0;

   // code >= 300 && < 400 is already handled above
   if (bodyp && (code < 100 || code >= 200) && code != 204) {
      // see if we should do a binary or string read
      content_encoding = get_string_header(xsink, **ans, "content-encoding");
      if (*xsink) {
	 disconnect_unlocked();
	 return 0;
      }

      if (content_encoding) {
	 // check for misuse (? not sure: check RFCs again) of this field by including a character encoding value
	 if (!strncasecmp(content_encoding, "iso", 3) || !strncasecmp(content_encoding, "utf-", 4)) {
	    msock->socket->setEncoding(QEM.findCreate(content_encoding));
	    content_encoding = 0;
	 }
	 else if (!recv_callback) {
	    // only decode message bodies automatically if there is no receive callback
	    if (!strcasecmp(content_encoding, "deflate") || !strcasecmp(content_encoding, "x-deflate"))
	       dec = qore_inflate_to_string;
	    else if (!strcasecmp(content_encoding, "gzip") || !strcasecmp(content_encoding, "x-gzip"))
	       dec = qore_gunzip_to_string;
	    else if (!strcasecmp(content_encoding, "bzip2") || !strcasecmp(content_encoding, "x-bzip2"))
	       dec = qore_bunzip2_to_string;
	 }
      }

      const char* te = get_string_header(xsink, **ans, "transfer-encoding");
      if (*xsink) {
	 disconnect_unlocked();
	 return 0;
      }
   
      // get response body, if any
      const char* cl = get_string_header(xsink, **ans, "content-length");
      if (*xsink) {
	 disconnect_unlocked();
	 return 0;
      }
      int len = cl ? atoi(cl) : 0;
      
      if (cl && cb_queue)
	 do_content_length_event(cb_queue, msock->socket->getObjectIDForEvents(), len);

      if (te && !strcasecmp(te, "chunked")) { // check for chunked response body
	 if (cb_queue)
	    do_event(cb_queue, msock->socket->getObjectIDForEvents(), QORE_EVENT_HTTP_CHUNKED_START);
	 ReferenceHolder<QoreHashNode> nah(xsink);
	 if (recv_callback) {
	    if (content_encoding)
	       msock->socket->priv->readHttpChunkedBodyBinary(timeout_ms, xsink, QORE_SOURCE_HTTPCLIENT, recv_callback, &msock->m, obj);
	    else
	       msock->socket->priv->readHttpChunkedBody(timeout_ms, xsink, QORE_SOURCE_HTTPCLIENT, recv_callback, &msock->m, obj);
	 }
	 else {
	    if (content_encoding)
	       nah = msock->socket->priv->readHttpChunkedBodyBinary(timeout_ms, xsink, QORE_SOURCE_HTTPCLIENT);
	    else
	       nah = msock->socket->priv->readHttpChunkedBody(timeout_ms, xsink, QORE_SOURCE_HTTPCLIENT);
	 }
	 if (cb_queue)
	    do_event(cb_queue, msock->socket->getObjectIDForEvents(), QORE_EVENT_HTTP_CHUNKED_END);
	 
	 if (!nah && !recv_callback) {
	    if (!msock->socket->isOpen())
	       disconnect_unlocked();
	    return 0;
	 }

	 if (info) {
	    info->setKeyValue("chunked", &True, xsink);
	    if (*xsink)
	       return 0;
	 }
	 
	 if (!recv_callback) {
	    body = nah->takeKeyValue("body");
	    ans->merge(*nah, xsink);
	 }
      }
      else if (getbody || len) {
	 if (content_encoding) {
	    SimpleRefHolder<BinaryNode> bobj(msock->socket->recvBinary(len, timeout_ms, xsink));
	    if (!(*xsink) && bobj)
	       body = bobj.release();
	 }
	 else {
	    QoreStringNodeHolder bstr(msock->socket->recv(len, timeout_ms, xsink));
	    if (!(*xsink) && bstr)
	       body = bstr.release();
	 }
	 
	 if (*xsink && !msock->socket->isOpen())
	    disconnect_unlocked();
	 //printf("body=%p\n", body);
      }  
   }

   // check for connection: close header
   if (!keep_alive)
      disconnect_unlocked();
   else {
      const char* conn = get_string_header(xsink, **ans, "connection", true);
      if (*xsink) {
	 disconnect_unlocked();
	 return 0;
      }
      if (conn && !strcasecmp(conn, "close"))
	 disconnect_unlocked();
   }

   sl.unlock();

   // for content-encoding processing we can run unlocked

   // add body to result hash and process content encoding if necessary
   if (body) {
      if (content_encoding) {
	 if (!dec) {
	    if (!recv_callback) {
	       xsink->raiseException("HTTP-CLIENT-RECEIVE-ERROR", "don't know how to handle content-encoding '%s'", content_encoding);
	       ans = 0;
	    }
	 }
	 else {
	    BinaryNode* bobj = reinterpret_cast<BinaryNode*>(body);
	    QoreStringNode* str = dec(bobj, msock->socket->getEncoding(), xsink);
	    bobj->deref();
	    body = str;
	 }
      }

      if (body) {
	 // send data to recv_callback (already unlocked)
	 if (recv_callback) {
	    ReferenceHolder<> bh(body, xsink);
	    if (msock->socket->priv->runDataCallback(xsink, mname, *recv_callback, 0, body, false)
		|| msock->socket->priv->runHeaderCallback(xsink, mname, *recv_callback, 0, 0, send_aborted, obj))
	       return 0;
	 }
	 else
	    ans->setKeyValue("body", body, xsink);
      }
   }

   // do not throw an exception if a receive callback is used
   if (!recv_callback && !*xsink && (code < 100 || code >= 300)) {
      const char* mess = get_string_header(xsink, **ans, "status_message");
      if (!mess)
	 mess = "<no message>";
      assert(!*xsink);

      xsink->raiseExceptionArg("HTTP-CLIENT-RECEIVE-ERROR", ans.release(), "HTTP status code %d received: message: %s", code, mess);
      return 0;
   }

   return *xsink || recv_callback ? 0 : ans.release();
}
コード例 #22
0
ファイル: interp.c プロジェクト: plesner/neutrino
// Validates that the stack looks correct after execution completes normally.
static void validate_stack_on_normal_exit(frame_t *frame) {
    value_t stack = get_stack_piece_stack(frame->stack_piece);
    CHECK_TRUE("leftover barriers", is_nothing(get_stack_top_barrier(stack)));
}
コード例 #23
0
int ForEachStatement::execRef(QoreValue& return_value, ExceptionSink* xsink) {
   int rc = 0;

   // instantiate local variables
   LVListInstantiator lvi(lvars, xsink);

   ParseReferenceNode* r = reinterpret_cast<ParseReferenceNode*>(list);

   // here we get the runtime reference
   ReferenceHolder<ReferenceNode> vr(r->evalToRef(xsink), xsink);
   if (*xsink)
      return 0;

   // get the current value of the lvalue expression
   ReferenceHolder<AbstractQoreNode> tlist(vr->eval(xsink), xsink);
   if (!code || *xsink || is_nothing(*tlist))
      return 0;

   QoreListNode* l_tlist = tlist->getType() == NT_LIST ? reinterpret_cast<QoreListNode*>(*tlist) : 0;
   if (l_tlist && l_tlist->empty())
      return 0;

   // execute "foreach" body
   ReferenceHolder<AbstractQoreNode> ln(0, xsink);
   unsigned i = 0;

   if (l_tlist)
      ln = new QoreListNode;

   while (true) {
      {
	 LValueHelper n(var, xsink);
	 if (!n)
	    return 0;

	 // assign variable to current value in list
	 if (n.assign(l_tlist ? l_tlist->get_referenced_entry(i) : tlist.release()))
	    return 0;
      }

      // set offset in thread-local data for "$#"
      ImplicitElementHelper eh(l_tlist ? (int)i : 0);

      // execute "for" body
      rc = code->execImpl(return_value, xsink);
      if (*xsink)
	 return 0;

      // get value of foreach variable
      AbstractQoreNode* nv = var->eval(xsink);
      if (*xsink)
	 return 0;

      // assign new value to temporary variable for later assignment to referenced lvalue
      if (l_tlist)
	 reinterpret_cast<QoreListNode*>(*ln)->push(nv);
      else
	 ln = nv;

      if (rc == RC_BREAK) {
	 // assign remaining values to list unchanged
	 if (l_tlist)
	    while (++i < l_tlist->size())
	       reinterpret_cast<QoreListNode*>(*ln)->push(l_tlist->get_referenced_entry(i));

	 rc = 0;
	 break;
      }

      if (rc == RC_RETURN)
	 break;
      else if (rc == RC_CONTINUE)
	 rc = 0;
      i++;

      // break out of loop if appropriate
      if (!l_tlist || i == l_tlist->size())
	 break;
   }

   // write the value back to the lvalue
   LValueHelper val(**vr, xsink);
   if (!val)
      return 0;

   if (val.assign(ln.release()))
      return 0;

   return rc;
}
コード例 #24
0
int ForEachStatement::execImpl(QoreValue& return_value, ExceptionSink* xsink) {
   if (is_ref)
      return execRef(return_value, xsink);

   if (is_keys)
      return execKeys(return_value, xsink);

   // instantiate local variables
   LVListInstantiator lvi(lvars, xsink);

   // get list evaluation (although may be a single node)
   ReferenceHolder<AbstractQoreNode> tlist(list->eval(xsink), xsink);
   if (!code || *xsink || is_nothing(*tlist))
      return 0;

   qore_type_t t = tlist->getType();
   QoreListNode* l_tlist = t == NT_LIST ? reinterpret_cast<QoreListNode*>(*tlist) : 0;
   if (l_tlist) {
      if (l_tlist->empty())
         return 0;
   }
   else if (t == NT_OBJECT) {
      // check for an object derived from AbstractIterator
      AbstractIteratorHelper aih(xsink, "map operator", reinterpret_cast<QoreObject*>(*tlist));
      if (*xsink)
         return 0;
      if (aih)
         return execIterator(aih, return_value, xsink);
   }

   // execute "foreach" body
   unsigned i = 0;

   int rc = 0;

   while (true) {
      {
	 LValueHelper n(var, xsink);
	 if (!n)
	    break;

	 // assign variable to current value in list
	 if (n.assign(l_tlist ? l_tlist->get_referenced_entry(i) : tlist.release()))
	    break;
      }

      // set offset in thread-local data for "$#"
      ImplicitElementHelper eh(l_tlist ? (int)i : 0);

      // execute "foreach" body
      if (((rc = code->execImpl(return_value, xsink)) == RC_BREAK) || *xsink) {
	 rc = 0;
	 break;
      }

      if (rc == RC_RETURN)
	 break;
      else if (rc == RC_CONTINUE)
	 rc = 0;
      i++;
      // if the argument is not a list or list iteration is done, then break
      if (!l_tlist || i == l_tlist->size())
	 break;
   }

   return rc;
}
コード例 #25
0
ファイル: QoreValue.cpp プロジェクト: temnoregg/qore
bool QoreValue::isNothing() const {
   return type == QV_Node && is_nothing(v.n);
}
コード例 #26
0
ファイル: test_tagged.c プロジェクト: plesner/neutrino
TEST(tagged, nothing) {
  value_t not = nothing();
  ASSERT_EQ(ENCODED_NOTHING, not.encoded);
  ASSERT_TRUE(is_nothing(not));
}