/* iterates through docs callbacks and calls any that have not yet been called */
static void check_docs_loaded(XMLRPC_SERVER server, void* userData) {
   if(server) {
      q_iter qi = Q_Iter_Head_F(&server->docslist);
      while( qi ) {
         doc_method* dm = Q_Iter_Get_F(qi);
         if(dm && !dm->b_called) {
            dm->method(server, userData);
            dm->b_called = 1;
         }
         qi = Q_Iter_Next_F(qi);
      }
   }
}
/* this complies with system.listMethods as defined at http://xmlrpc.usefulinc.com/doc/reserved.html */
static XMLRPC_VALUE xi_system_list_methods_cb(XMLRPC_SERVER server, XMLRPC_REQUEST input, void* userData) {
   XMLRPC_VALUE xResponse = XMLRPC_CreateVector(NULL, xmlrpc_vector_array);

   q_iter qi = Q_Iter_Head_F(&server->methodlist);
   while( qi ) {
      server_method* sm = Q_Iter_Get_F(qi);
      if(sm) {
         XMLRPC_VectorAppendString(xResponse, 0, sm->name, 0);
      }
      qi = Q_Iter_Next_F(qi);
   }
   return xResponse;
}
/* system.describeMethods() callback */
static XMLRPC_VALUE xi_system_describe_methods_cb(XMLRPC_SERVER server, XMLRPC_REQUEST input, void* userData) {
   XMLRPC_VALUE xParams = XMLRPC_VectorRewind(XMLRPC_RequestGetData(input));
   XMLRPC_VALUE xResponse = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
   XMLRPC_VALUE xMethodList = XMLRPC_CreateVector("methodList", xmlrpc_vector_array);
   XMLRPC_VALUE xTypeList = NULL;
   int bAll = 1;

   /* lazy loading of introspection data */
   check_docs_loaded(server, userData);

   xTypeList = XMLRPC_VectorGetValueWithID(server->xIntrospection, "typeList");

   XMLRPC_AddValueToVector(xResponse, xTypeList);
   XMLRPC_AddValueToVector(xResponse, xMethodList);

   /* check if we have any param */
   if(xParams) {
      /* check if string or vector (1 or n) */
      XMLRPC_VALUE_TYPE type = XMLRPC_GetValueType(xParams);
      if(type == xmlrpc_string) {
         /* just one.  spit it out. */
         describe_method(server, xMethodList, XMLRPC_GetValueString(xParams));
         bAll = 0;
      }
      else if(type == xmlrpc_vector) {
         /* multiple.  spit all out */
         XMLRPC_VALUE xIter = XMLRPC_VectorRewind(xParams);
         while(xIter) {
            describe_method(server, xMethodList, XMLRPC_GetValueString(xIter));
            xIter = XMLRPC_VectorNext(xParams);
         }
         bAll = 0;
      }
   }

   /* otherwise, default to sending all methods */
   if(bAll) {
      q_iter qi = Q_Iter_Head_F(&server->methodlist);
      while( qi ) {
         server_method* sm = Q_Iter_Get_F(qi);
         if(sm) {
            XMLRPC_AddValueToVector(xMethodList, sm->desc);
         }
         qi = Q_Iter_Next_F(qi);
      }
   }
   
   return xResponse;
}