void QMetaObjectPublisher::signalEmitted(const QObject *object, const int signalIndex, const QVariantList &arguments)
{
    if (!webChannel || webChannel->d_func()->transports.isEmpty()) {
        if (signalIndex == s_destroyedSignalIndex)
            objectDestroyed(object);
        return;
    }
    if (!signalToPropertyMap.value(object).contains(signalIndex)) {
        QJsonObject message;
        const QString &objectName = registeredObjectIds.value(object);
        Q_ASSERT(!objectName.isEmpty());
        message[KEY_OBJECT] = objectName;
        message[KEY_SIGNAL] = signalIndex;
        if (!arguments.isEmpty()) {
            message[KEY_ARGS] = wrapList(arguments);
        }
        message[KEY_TYPE] = TypeSignal;
        broadcastMessage(message);

        if (signalIndex == s_destroyedSignalIndex) {
            objectDestroyed(object);
        }
    } else {
        pendingPropertyUpdates[object][signalIndex] = arguments;
        if (clientIsIdle && !blockUpdates && !timer.isActive()) {
            timer.start(PROPERTY_UPDATE_INTERVAL, this);
        }
    }
}
PairUint
getCharInterval(void *space,
            Suffixarray *s,
            Uint i,
            Uint j,
            Uint pos,
            char ch) 
{
    List *list;
    Uint lcp=0;
    PairUint lr;
    
    lr.a = 1;
    lr.b = 0;
    
    if(i==j) return lr;

    list = getChildintervals(space, s, i, j);
    lcp = getlcpval(s, i, j);

    for(i=0; i < list->length; i++) {

      if(s->suffixptr[s->suftab[((PairUint*)list->nodes[i].data)->a]][lcp] == ch) {
            lr.a = ((PairUint*)list->nodes[i].data)->a;       
            lr.b = ((PairUint*)list->nodes[i].data)->b;
            break;
        }
    }
    wrapList(space, list, destructinterval);
    return lr;
}
QJsonValue QMetaObjectPublisher::wrapResult(const QVariant &result)
{
    if (QObject *object = result.value<QObject *>()) {
        QJsonObject objectInfo;
        objectInfo[KEY_QOBJECT] = true;
        QString id = registeredObjectIds.value(object);
        if (id.isEmpty()) {
            // neither registered, nor wrapped, do so now
            id = QUuid::createUuid().toString();

            registeredObjectIds[object] = id;
            registeredObjects[id] = object;

            QJsonObject info = classInfoForObject(object);
            wrappedObjects[object] = info;
            objectInfo[KEY_DATA] = info;
            if (propertyUpdatesInitialized) {
                // if other objects are initialized already, do the same here
                initializePropertyUpdates(object, info);
            }
        } else if (wrappedObjects.contains(object)) {
            // if this object was wrapped, send the full class info
            // this is required for proper multi-client support
            objectInfo[KEY_DATA] = wrappedObjects.value(object);
        }

        objectInfo[KEY_ID] = id;
        return objectInfo;
    } else if (result.canConvert<QVariantList>()) {
        // recurse and potentially wrap contents of the array
        return wrapList(result.toList());
    }

    // no need to wrap this
    return QJsonValue::fromVariant(result);
}
void
constructsuflinks(void *space, Suffixarray *s) {

  Uint   i,
         j,
         a,
         b,
         k,
         nooflists,
         lcp,
         pos;
  Stack  istack;
  Stack  jstack;

  List   *children,
         **lists;
  PairUint **data,
           slinkinterval;

  nooflists = maxlcp(s) +1;
  lists = ALLOCMEMORY(space, NULL, List*, nooflists);
  memset(lists, 0, sizeof(List*)*nooflists);

  initStack(space, &istack, 1000);
  initStack(space, &jstack, 1000);

  stackpush(space, &istack, 0);
  stackpush(space, &jstack, s->numofsuffixes-1);

  while(!stackisempty(&istack)) {
    i = stackpop(&istack);
    j = stackpop(&jstack);
    lcp = getlcpval(s, i, j);

    /*printf("adding list %d\n", lcp);*/
    if (lists[lcp] == NULL) {
      lists[lcp] = initList(space, 10);
    }

    addinterval(space, lists[lcp], i, j);

    /*printf("lcp: %d-[%d,%d]\n", lcp, i, j);*/
    children = getChildintervals(space, s, i, j);
    data = (PairUint**) dataList(space, children);

    for(k=children->length; k > 0; k--) {
      a = data[k-1]->a;
      b = data[k-1]->b;

      FREEMEMORY(space, data[k-1]);

      if(a != b) { 
        stackpush(space, &istack, a);
        stackpush(space, &jstack, b);
      }
    }

    FREEMEMORY(space, data);
    wrapList(space, children, NULL);
  }

  destructStack(space, &istack);
  destructStack(space, &jstack);

  s->suflink_l = ALLOCMEMORY(space, NULL, Uint, s->numofsuffixes);
  s->suflink_r = ALLOCMEMORY(space, NULL, Uint, s->numofsuffixes);
  memset(s->suflink_l, 0, sizeof(Uint)*s->numofsuffixes);
  memset(s->suflink_r, 0, sizeof(Uint)*s->numofsuffixes);

  for(i=1; i < nooflists; i++) {
    if(lists[i] !=  NULL && lists[i-1] !=NULL) {
      for(j=0; j < lists[i]->length; j++) {
       /*printf("looking at interval [%d,%d], list %d\n", ((PairUint*)lists[i]->nodes[j].data)->a, ((PairUint*)lists[i]->nodes[j].data)->b, i);*/
        slinkinterval = findslinkinterval(space, s, lists, i, j);
        pos = getfirstlindex(s, ((PairUint*)lists[i]->nodes[j].data)->a, ((PairUint*)lists[i]->nodes[j].data)->b);
       /*printf("store at %d: [%d,%d]\n", pos, slinkinterval.a, slinkinterval.b);*/
        s->suflink_l[pos]=slinkinterval.a;
        s->suflink_r[pos]=slinkinterval.b;
      }
    }
    wrapList(space, lists[i-1], destructinterval);
  }

  FREEMEMORY(space, lists);
  return;
}