Exemple #1
0
SEXP graph_bitarray_getEdgeAttrOrder(SEXP _bits, SEXP _from, SEXP _to) {
    unsigned char *bits = (unsigned char*) RAW(_bits);
    int ns = asInteger(getAttrib(_bits, install("nbitset")));
    int len = length(_from);
    int *from = INTEGER(_from);
    int *to = INTEGER(_to);
    int dim = NROW(_bits);
    int byteIndex, bitIndex, shft, indx, intIndx, i, j;
    int oindx=0, nindx=0, attrIndx=0, setCount=0;
    SEXP origRightPos, origLeftPos, newRightPos, newLeftPos, res, namesres;
    PROTECT(origRightPos = allocVector(INTSXP, ns)); //index into orig attr
    PROTECT(origLeftPos = allocVector(INTSXP, ns));
    PROTECT(newRightPos = allocVector(INTSXP, len));
    PROTECT(newLeftPos = allocVector(INTSXP, len));

    setCount =1;
    for(j =0; j < dim ; j ++) {
        for(i =0; i < dim; i++){
            indx =  COORD_TO_INDEX(i, j , dim);
            byteIndex = indx / 8;
            bitIndex = indx % 8;
            shft = 1 << bitIndex;
            intIndx = COORD_TO_INDEX(from[attrIndx]-1, to[attrIndx]-1, dim);
            if(bits[byteIndex] & (shft) ) {
                INTEGER(origRightPos)[oindx]  = oindx + 1  ;
                INTEGER(origLeftPos)[oindx] = setCount    ;
                oindx++;
                if(intIndx != indx){
                   setCount++; 
                }
            }
            if(intIndx == indx) {
               INTEGER(newRightPos)[nindx] =  nindx + 1;
               INTEGER(newLeftPos)[nindx] = setCount  ;
               nindx++;
               if(attrIndx < len-1){
                   attrIndx++; 
               }  
               setCount++;
            }
        }
    }
    SET_LENGTH(newRightPos, nindx);
    SET_LENGTH(newLeftPos, nindx);
    
    PROTECT(res = allocVector(VECSXP, 4));
    SET_VECTOR_ELT(res, 0, newLeftPos);
    SET_VECTOR_ELT(res, 1, newRightPos); 
    SET_VECTOR_ELT(res, 2, origLeftPos); 
    SET_VECTOR_ELT(res, 3, origRightPos); 
    PROTECT(namesres = allocVector(STRSXP, 4));
    SET_STRING_ELT(namesres, 0, mkChar("newLeftPos"));
    SET_STRING_ELT(namesres, 1, mkChar("newRightPos"));
    SET_STRING_ELT(namesres, 2, mkChar("origLeftPos"));
    SET_STRING_ELT(namesres, 3, mkChar("origRightPos"));
    setAttrib(res, R_NamesSymbol, namesres);
    UNPROTECT(6);
    return(res);

}
Exemple #2
0
/**
 * abstracts some of the content of the add to binary tree function. 
 * specifically the part where location to add the new node is found and
 * the current node takes the values of the node to be added.
 * @param node_to_add 
 * @param return_competitor a pointer to a competitor * so that we can set the
 * values of it and pass them back out of the function
 * @return the appropriate flags for any errors that occur
 */
int set_current(competitor * node_to_add,
        competitor ** return_competitor){
    competitor * current = calloc(1, sizeof(competitor));
    if(current == NULL) return MEMORY_ALLOCATION_FAILURE;
    
    current->left = current->right = NULL;
    /* macros used, just to simplify repeated code */
    SET_LENGTH(bean_length);
    SET_LENGTH(carrot_length);
    SET_LENGTH(cucumber_length);
    current->name = node_to_add->name;
    current->address = node_to_add->address;
    current->phone_number = node_to_add->phone_number;
    current->ID = node_to_add->ID;
    (*return_competitor) = current;   
    return 0;
}
TInt DISICLTransceiver::SendCommIsaEntityNotReachableResp(
        TDes8& aNotDeliveredMessage
        )
    {
    C_TRACE( ( _T( "DISICLTransceiver::SendCommIsaEntityNotReachableResp 0x%x>" ), &aNotDeliveredMessage ) );
    const TUint8* notDeliveredMsgPtr( aNotDeliveredMessage.Ptr() );
    TInt error = KErrAlreadyExists;
    // Avoid COMM_ISA_ENTITY_NOT_REACHABLE_RESP loop.
    if( ( notDeliveredMsgPtr[ ISI_HEADER_OFFSET_MESSAGEID ] == COMMON_MESSAGE ) &&
        ( ( notDeliveredMsgPtr[ ISI_HEADER_OFFSET_SUBMESSAGEID ] == COMM_ISA_ENTITY_NOT_REACHABLE_RESP ) || 
          ( notDeliveredMsgPtr[ ISI_HEADER_OFFSET_SUBMESSAGEID ] == COMM_SERVICE_NOT_IDENTIFIED_RESP ) ) )
        {
        C_TRACE( ( _T( "DISICLTransceiver Not sending another CommIsaEntityNotReachableResp 0x%x 0x%x" ), &aNotDeliveredMessage, notDeliveredMsgPtr[ ISI_HEADER_OFFSET_SUBMESSAGEID ] ) );
        }
    else
        {
        // Follows COMM specification: 000.031
        TUint8 length( ISI_HEADER_SIZE + SIZE_COMMON_MESSAGE_COMM_ISA_ENTITY_NOT_REACHABLE_RESP );
        TDes8& respMsg = MemApi::AllocBlock( length );
        ASSERT_RESET_ALWAYS( length > ISI_HEADER_OFFSET_MESSAGEID, ( EISICLTransceiverOverTheLimits | EDISICLTransceiverTraceId << KClassIdentifierShift ) );
        TUint8* respMsgPtr = const_cast<TUint8*>( respMsg.Ptr() );
        // We start to append from transaction id.
        respMsg.SetLength( ISI_HEADER_OFFSET_TRANSID );
        // Get the header until messageid from prev. message.
        // Just turn receiver and sender device and object vice versa.
        respMsgPtr[ ISI_HEADER_OFFSET_MEDIA ] = notDeliveredMsgPtr[ ISI_HEADER_OFFSET_MEDIA ];
        SET_RECEIVER_DEV( respMsgPtr, GET_SENDER_DEV( aNotDeliveredMessage ) );
        SET_SENDER_DEV  ( respMsgPtr, GET_RECEIVER_DEV( aNotDeliveredMessage ) );
        respMsgPtr[ ISI_HEADER_OFFSET_RESOURCEID ] = notDeliveredMsgPtr[ ISI_HEADER_OFFSET_RESOURCEID ];
        SET_LENGTH( respMsgPtr, ( length - PN_HEADER_SIZE ) );
        SET_RECEIVER_OBJ( respMsgPtr, GET_SENDER_OBJ( aNotDeliveredMessage ) );
        SET_SENDER_OBJ( respMsgPtr, GET_RECEIVER_OBJ( aNotDeliveredMessage ) );
        // Set from undelivered message
        respMsg.Append( notDeliveredMsgPtr[ ISI_HEADER_OFFSET_TRANSID ] );
        // Message Identifier
        respMsg.Append( COMMON_MESSAGE );
        // Sub message Identifier.
        respMsg.Append( COMM_ISA_ENTITY_NOT_REACHABLE_RESP );
        // Not Delivered Message from original message.
        respMsg.Append( notDeliveredMsgPtr[ ISI_HEADER_OFFSET_MESSAGEID ] );
        // Status
        respMsg.Append( COMM_ISA_ENTITY_NOT_AVAILABLE );//  different status in a case of device not existing
        // Filler
        const TUint8 KFiller( 0x00 );
        respMsg.Append( KFiller );
        // Filler
        respMsg.Append( KFiller );
        // Filler
        respMsg.Append( KFiller );
        error = RouteISIMessage( respMsg, EFalse );
        // Programming error in this function if below assert is raised
        ASSERT_RESET_ALWAYS( KErrNone == error, ( EISICLTransceiverCommIsaEntityNotReachableResp | EDISICLTransceiverTraceId << KClassIdentifierShift ) );        
        }
    MemApi::DeallocBlock( aNotDeliveredMessage );
    C_TRACE( ( _T( "DISICLTransceiver::SendCommIsaEntityNotReachableResp 0x%x<" ), &aNotDeliveredMessage ) );
    return error;

    }
Exemple #4
0
/*
#define  xts_IndexSymbol        install("index")
#define  xts_ClassSymbol        install(".CLASS")
#define  xts_IndexFormatSymbol  install(".indexFORMAT")
#define  xts_IndexClassSymbol   install(".indexCLASS")
#define  xts_ATTRIB(x)          coerceVector(do_xtsAttributes(x),LISTSXP)
*/
SEXP do_xtsAttributes(SEXP x)
{
  SEXP a, values, names;
  int i=0, P=0;

  a = ATTRIB(x);
  if(length(a) <= 0)
    return R_NilValue;
  PROTECT(a); P++; /* all attributes */
  PROTECT(values = allocVector(VECSXP, length(a))); P++;
  PROTECT(names  = allocVector(STRSXP, length(a))); P++;

  /*
   CAR gets the first element of the dotted pair list
   CDR gets the rest of the dotted pair list
   TAG gets the symbol/name of the first element of dotted pair list
  */
  for( /* a=ATTRIB(a) */; a != R_NilValue; a = CDR(a) ) {
    if(TAG(a) != xts_IndexSymbol &&
       TAG(a) != xts_ClassSymbol &&
       TAG(a) != xts_IndexFormatSymbol &&
       TAG(a) != xts_IndexClassSymbol &&
       TAG(a) != xts_IndexTZSymbol &&
       TAG(a) != R_ClassSymbol &&
       TAG(a) != R_DimSymbol &&
       TAG(a) != R_DimNamesSymbol &&
       TAG(a) != R_NamesSymbol)
    {
      SET_VECTOR_ELT(values, i, CAR(a));
      SET_STRING_ELT(names,  i, PRINTNAME(TAG(a)));
      i++;
    }
  }
  if(i == 0) {
    UNPROTECT(P);
    return R_NilValue;
  }

  SET_LENGTH(values, i); /* truncate list back to i-size */
  SET_LENGTH(names,  i);
  setAttrib(values, R_NamesSymbol, names);
  UNPROTECT(P);
  return values;
}
Exemple #5
0
void RS_DBI_allocOutput(SEXP output, RMySQLFields* flds, int num_rec, int  expand) {
  SEXP names, s_tmp;
  int   j;
  int    num_fields;
  SEXPTYPE  *fld_Sclass;

  PROTECT(output);

  num_fields = flds->num_fields;
  if(expand){
    for(j = 0; j < (int) num_fields; j++){
      /* Note that in R-1.2.3 (at least) we need to protect SET_LENGTH */
      s_tmp = LST_EL(output,j);
      PROTECT(SET_LENGTH(s_tmp, num_rec));
      SET_ELEMENT(output, j, s_tmp);
      UNPROTECT(1);
    }
    UNPROTECT(1);
    return;
  }

  fld_Sclass = flds->Sclass;
  for(j = 0; j < (int) num_fields; j++){
    switch((int)fld_Sclass[j]){
    case LGLSXP:
      SET_ELEMENT(output, j, NEW_LOGICAL(num_rec));
      break;
    case STRSXP:
      SET_ELEMENT(output, j, NEW_CHARACTER(num_rec));
      break;
    case INTSXP:
      SET_ELEMENT(output, j, NEW_INTEGER(num_rec));
      break;
    case REALSXP:
      SET_ELEMENT(output, j, NEW_NUMERIC(num_rec));
      break;
    case VECSXP:
      SET_ELEMENT(output, j, NEW_LIST(num_rec));
      break;
    default:
      error("unsupported data type");
    }
  }

  PROTECT(names = NEW_CHARACTER((int) num_fields));
  for(j = 0; j< (int) num_fields; j++){
    SET_CHR_EL(names,j, mkChar(flds->name[j]));
  }
  SET_NAMES(output, names);

  UNPROTECT(2);

  return;
}
Exemple #6
0
void rsqlite_output_expand(SEXP output, SQLiteFields* flds, int num_rec) {
  PROTECT(output);
  int p = flds->num_fields;

  for (int j = 0; j < p; j++) {
    /* Note that in R-1.2.3 (at least) we need to protect SET_LENGTH */
    SEXP s_tmp = VECTOR_ELT(output, j);
    PROTECT(SET_LENGTH(s_tmp, num_rec));
    SET_VECTOR_ELT(output, j, s_tmp);
    UNPROTECT(1);
  }
  UNPROTECT(1);
}
Exemple #7
0
void
R_tarCollectContents(const char *fname, char *bytes, unsigned int numBytes, unsigned int remaining, void *data)
{
    RTarCallInfo *cb = (RTarCallInfo *)data;
    int len = 0;

    if(numBytes < 1) {
	/* Invoke the function to signal the completion of a file. */

        /* Need to make this have the correct length, i.e. cb->offset */
        SEXP tmp = cb->rawData;
        if(GET_LENGTH(cb->rawData) > cb->offset) {
 	    tmp = allocVector(RAWSXP, cb->offset); /* shouldn't need to protect. */
	    memcpy(RAW(tmp), RAW(cb->rawData), cb->offset);
	}
	SETCAR(CDR(cb->e), tmp);
	SETCAR(CDR(CDR(cb->e)), mkString(fname));
	Rf_eval(cb->e, R_GlobalEnv);

	cb->offset = 0;
	
	return;
    }

    /* If we don't preallocate rawData, then this will continue
       to grow the vector just enough to fit the new bytes.*/
    if(cb->rawData == R_NilValue) 
	cb->rawData = allocVector(RAWSXP, numBytes);
    else {
	len = LENGTH(cb->rawData);
        if(len - cb->offset < numBytes) {
	    SET_LENGTH(cb->rawData, len + numBytes);
	    PROTECT(cb->rawData); 
	    cb->numProtects++;
	}
    }

    memcpy(RAW(cb->rawData) + cb->offset, bytes, numBytes);
    cb->offset += numBytes;
}
Exemple #8
0
/*#define DEBUG 1*/
SEXP locate_byte_sequences(SEXP buf, SEXP match, SEXP len, SEXP key, SEXP max)
{
  /*
   * locate_byte_sequences() = function to be used for e.g. nortek adp / adv files
   * buf = buffer to be scanned
   * match = set of bytes that mark start of sequences
   * len = length of sequence
   * key = key added to checksum, and to be checked against last 2 bytes of sequence
   * max = 0 to use whole buffer, positive integer to limit to that many matches
   */

  /* 
     R CMD SHLIB bitwise.c 
     */
  /*
     library(oce)
     f <- "/Users/kelley/data/archive/sleiwex/2008/moorings/m06/adv/nortek_1943/raw/adv_nortek_1943.vec"
     buf <- readBin(f, what="raw", n=1e6)
     vvd.start <- matchBytes(buf, 0xa5, 0x10)
     dyn.load("~/src/R-kelley/oce/src/bitwise.so")
     s <- .Call("locate_byte_sequences",buf, c(0xa5, 0x10), 24, c(0xb5, 0x8c), 0)
     print(s)
     print(vvd.start)
     */
  unsigned char *pbuf, *pmatch, *pkey;
  PROTECT(buf = AS_RAW(buf));
  PROTECT(match = AS_RAW(match));
  PROTECT(len = AS_INTEGER(len));
  PROTECT(key = AS_RAW(key));
  PROTECT(max = AS_INTEGER(max));
  /* FIXME: check lengths of match and key */
  pbuf = RAW_POINTER(buf);
  pmatch = RAW_POINTER(match);
  pkey = RAW_POINTER(key);
  int lsequence = *INTEGER_POINTER(len);
  int max_lres = *INTEGER_POINTER(max);
#ifdef DEBUG
  Rprintf("lsequence=%d\n",lsequence);
#endif
  int lmatch = LENGTH(match);
  int lbuf = LENGTH(buf);
  int lkey = LENGTH(key);
  if (lkey != 2) error("key length must be 2");
  int ires = 0, lres = (int)(lbuf / lsequence + 3); /* get some extra space; fill some with NA */
  SEXP res;
#ifdef DEBUG
  Rprintf("lsequence=%d, lres=%d\n",lsequence,lres);
#endif
  /* Rprintf("max_lres=%d\n", max_lres); */
  if (max_lres > 0)
    lres = max_lres;
  PROTECT(res = NEW_INTEGER(lres));
  int *pres = INTEGER_POINTER(res);
  /* Count matches, so we can allocate the right length */
  short lsequence2 = lsequence / 2;
  for (int i = 0; i < lbuf - lsequence; i++) {
    short check_value = (((short)pkey[0]) << 8) | (short)pkey[1];
    int found = 0;
    for (int m = 0; m < lmatch; m++) {
      if (pbuf[i+m] == pmatch[m]) 
        found++;
      else
        break;
    }
    if (found == lmatch) {
      /* FIXME: should bit-twiddle this to work on all endian types */
      short *check = (short*)(pbuf+i);
      /*Rprintf(" %d", check_value);*/
      for (int cc = 0; cc < lsequence2 - 1; cc++) { /* last 2-byte chunk is the test value */
        check_value += *check++;
        /*Rprintf(" %d", check_value);*/
      }
      short check_sum = (((short)pbuf[i+lsequence-1]) << 8) | (short)pbuf[i+lsequence-2];
#ifdef DEBUG
      Rprintf("i=%d lbuf=%d ires=%d  lres=%d  check_value=%d vs check_sum %d match=%d\n", i, lbuf, ires, lres, check_value, check_sum, check_value==check_sum);
#endif
      if (check_value == check_sum) {
        pres[ires++] = i + 1;
        i += lsequence - lmatch; /* no need to check within sequence */
      }
      if (ires >= lres)
        break;
    }
    i += lmatch - 1;           /* skip over matched bytes */
    if (i > (lbuf - lsequence)) 
      break; /* FIXME: can this ever happen? */
  }
  SET_LENGTH(res, ires);
  UNPROTECT(6);
  return(res);
}
Exemple #9
0
/*#define DEBUG 1*/
SEXP locate_vector_imu_sequences(SEXP buf)
{
  /*
   * imu = Inertial Motion Unit (system-integrator-manual_Dec2014_jan.pdf p30-32)
   *
   * *(buf)     0xa5
   * *(buf+1)   0x71
   * *(buf+2,3) int, # bytes in structure
   * There are 3 possibilities, keyed by *(buf+6), "K", say
   *
   * Case |  K   | Contents
   * =====|======|=====================================================================
   *   A  | 0xc2 | ?
   *   B  | 0xcc | Acceleration, Angular Rate, Magnetometer Vectors, Orientation Matrix
   *   C  | 0xd2 | Gyro-stabilized Acceleration, Angular Rate, Magnetometer Vectors
   *   D  | 0xd3 | DeltaAngle, DeltaVelocity, Magnetometer Vectors
   *
   * QUESTION: what is AHRSchecksum? do we check that? And what is
   * this second 'Checksum'?
   * Case A has checksum starting at offset 84 (sum of all words in structure)
   */

  /* 

     library(oce)
     system("R CMD SHLIB bitwise.c")
     dyn.load("bitwise.so")
     f <- "/Users/kelley/src/dolfyn/example_data/vector_data_imu01.VEC"
     buf <- readBin(f, what="raw", n=1e5) 
     a <- .Call("locate_vector_imu_sequences", buf)
     for (aa in a[1:10]) {
         message(paste(paste("0x", buf[aa+seq.int(0, 6L)], sep=""), collapse=" "))
     }
     ensembleCounter <- as.numeric(buf[a + 4])
     plot(seq_along(a), ensembleCounter, type='l')


     */
  PROTECT(buf = AS_RAW(buf));
  unsigned char *bufp;
  bufp = RAW_POINTER(buf);
  int bufn = LENGTH(buf);
  SEXP res;
  PROTECT(res = NEW_INTEGER(bufn)); // definitely more than enough space
  int *resp = INTEGER_POINTER(res);
  int resn = 0;
  //int check=10; // check this many instance of 0xa5,0x71
  // We check 5 bytes, on the assumption that false positives will be
  // effectively zero then (1e-12, if independent random numbers
  // in range 0 to 255).
  // FIXME: test the checksum, but SIG2 does not state how.
  for (int i = 0; i < bufn-1; i++) {
    if (bufp[i] == 0xa5 && bufp[i+1] == 0x71) {
      //if (check-- > 0) Rprintf("IMU test: buf[%d]=0x%02x, buf[%d+2]=0x%02x, buf[%d+5]=0x%02x\n", i, bufp[i], i, bufp[i+2], i, bufp[i+5]);
      // Check at offset=5, which must be 1 of 3 choices.
      if (bufp[i+5] == 0xc3) {
        // FIXME: should verify this length check, which I got by inspecting dolfyn code
        // and a file provided privately in March 2016.
        if (bufp[i+2] == 0x24 && bufp[i+3] == 0x00) {
          resp[resn++] = i + 1; // add 1 for R notation
          i++; //FIXME: skip to end, when we really trust identification
        }
      } else if (bufp[i+5] == 0xcc) {
        // length indication should be 0x2b=43=86/2 (SIG2, top of page 31)
        if (bufp[i+2] == 0x2b && bufp[i+3] == 0x00) {
          resp[resn++] = i + 1; // add 1 for R notation
          i++; //FIXME: skip to end, when we really trust identification
        }
      } else if (bufp[i+5] == 0xd2) { // decimal 210
        // length indication should be 0x19=25=50/2 (SIG2, middle of page 31)
        if (bufp[i+2] == 0x19 && bufp[i+3] == 0x00) {
          resp[resn++] = i + 1; // add 1 for R notation
          i++; //FIXME: skip to end, when we really trust identification
        }
      } else if (bufp[i+5] ==0xd3) { // decimal 211
        // length indication should be 0x19=25=50/2 (SIG2, page 32)
        if (bufp[i+2] == 0x19 && bufp[i+3] == 0x00) {
          resp[resn++] = i + 1; // add 1 for R notation
          i++; //FIXME: skip to end, when we really trust identification
        }
      }
    }
  }
  SET_LENGTH(res, resn);
  UNPROTECT(2);
  return(res);
}
Exemple #10
0
/* Return a data.frame containing the requested number of rows from
   the resultset.

   We try to determine the correct R type for each column in the
   result.  Currently, type detection happens only for the first fetch
   on a given resultset and the first row of the resultset is used for
   type interpolation.  If a NULL value appears in the first row of
   the resultset and the column corresponds to a DB table column, we
   guess the type based on the DB schema definition for the column.
   If the NULL value does not correspond to a table column, then we
   force character.
*/
SEXP rsqlite_query_fetch(SEXP handle, SEXP max_rec) {
  SQLiteResult* res = rsqlite_result_from_handle(handle);
  if (res->isSelect != 1) {
    warning("resultSet does not correspond to a SELECT statement");
    return R_NilValue;
  }
  if (res->completed == 1) {
    return R_NilValue;
  }

  /* We need to step once to be able to create the data mappings */
  int row_idx = 0;
  int state = do_select_step(res, row_idx);
  sqlite3_stmt* db_statement = (sqlite3_stmt*) res->drvResultSet;

  if (state != SQLITE_ROW && state != SQLITE_DONE) {
    error("rsqlite_query_fetch: failed first step: %s",
        sqlite3_errmsg(sqlite3_db_handle(db_statement)));
  }

  SQLiteFields* flds = rsqlite_result_fields(res);

  int num_fields = flds->num_fields;
  int num_rec = asInteger(max_rec);
  int expand = (num_rec < 0);   /* dyn expand output to accommodate all rows*/
  if (expand || num_rec == 0) {
    num_rec = rsqlite_driver()->fetch_default_rec;
  }

  SEXP output = PROTECT(NEW_LIST(num_fields));
  rsqlite_output_alloc(output, flds, num_rec);
  while (state != SQLITE_DONE) {
    fill_one_row(db_statement, output, row_idx, flds);
    row_idx++;
    if (row_idx == num_rec) {  /* request satisfied or exhausted allocated space */
      if (expand) {    /* do we extend or return the records fetched so far*/
        num_rec = 1.5 * num_rec;
        rsqlite_output_expand(output, flds, num_rec);
      } else {
        break;       /* okay, no more fetching for now */
      }
    }
    state = do_select_step(res, row_idx);
    if (state != SQLITE_ROW && state != SQLITE_DONE) {
      error("rsqlite_query_fetch: failed: %s",
          sqlite3_errmsg(sqlite3_db_handle(db_statement)));
    }
  } /* end row loop */

  if (state == SQLITE_DONE) {
    res->completed = 1;
  }

  /* size to actual number of records fetched */
  if (row_idx < num_rec) {
    num_rec = row_idx;
    /* adjust the length of each of the members in the output_list */
    for (int j = 0; j < num_fields; j++) {
      SEXP s_tmp = VECTOR_ELT(output, j);
      PROTECT(SET_LENGTH(s_tmp, num_rec));
      SET_VECTOR_ELT(output, j, s_tmp);
      UNPROTECT(1);
    }
  }
  res->rowCount += num_rec;
  UNPROTECT(1);
  return output;
}
Exemple #11
0
// output is a named list
SEXP RS_MySQL_fetch(SEXP rsHandle, SEXP max_rec) {
  MySQLDriver   *mgr;
  RS_DBI_resultSet *result;
  RMySQLFields* flds;
  MYSQL_RES *my_result;
  MYSQL_ROW  row;
  SEXP output, s_tmp;

  unsigned long  *lens;
  int    i, j, null_item, expand;
  int   completed;
  SEXPTYPE  *fld_Sclass;
  int   num_rec;
  int    num_fields;

  result = RS_DBI_getResultSet(rsHandle);
  flds = result->fields;
  if(!flds)
    error("corrupt resultSet, missing fieldDescription");
  num_rec = asInteger(max_rec);
  expand = (num_rec < 0);   // dyn expand output to accommodate all rows
  if(expand || num_rec == 0){
    mgr = rmysql_driver();
    num_rec = mgr->fetch_default_rec;
  }
  num_fields = flds->num_fields;
  PROTECT(output = NEW_LIST((int) num_fields));
  RS_DBI_allocOutput(output, flds, num_rec, 0);
  fld_Sclass = flds->Sclass;

  // actual fetching....
  my_result = (MYSQL_RES *) result->drvResultSet;
  completed = (int) 0;

  for(i = 0; ; i++){
    if(i==num_rec){  // exhausted the allocated space

      if(expand){    // do we extend or return the records fetched so far
        num_rec = 2 * num_rec;
        RS_DBI_allocOutput(output, flds, num_rec, expand);
      }
      else
        break;       // okay, no more fetching for now
    }
    row = mysql_fetch_row(my_result);
    if(row==NULL){    // either we finish or we encounter an error
      unsigned int  err_no;
      RS_DBI_connection   *con;
      con = RS_DBI_getConnection(rsHandle);
      err_no = mysql_errno((MYSQL *) con->drvConnection);
      completed = (int) (err_no ? -1 : 1);
      break;
    }
    lens = mysql_fetch_lengths(my_result);

    for(j = 0; j < num_fields; j++){

      null_item = (row[j] == NULL);

      switch((int)fld_Sclass[j]){

      case INTSXP:
        if(null_item)
          NA_SET(&(LST_INT_EL(output,j,i)), INTSXP);
        else
          LST_INT_EL(output,j,i) = (int) atol(row[j]);
        break;

      case STRSXP:
        // BUG: I need to verify that a TEXT field (which is stored as
        // a BLOB by MySQL!) is indeed char and not a true
        // Binary obj (MySQL does not truly distinguish them). This
        // test is very gross.
        if(null_item)
          SET_LST_CHR_EL(output,j,i,NA_STRING);
        else {
          if((size_t) lens[j] != strlen(row[j])){
            warning("internal error: row %d field %d truncated", i, j);
          }
          SET_LST_CHR_EL(output,j,i,mkChar(row[j]));
        }
        break;

      case REALSXP:
        if(null_item)
          NA_SET(&(LST_NUM_EL(output,j,i)), REALSXP);
        else
          LST_NUM_EL(output,j,i) = (double) atof(row[j]);
        break;

      default:  // error, but we'll try the field as character (!)
        if(null_item)
          SET_LST_CHR_EL(output,j,i, NA_STRING);
        else {
          warning("unrecognized field type %d in column %d", fld_Sclass[j], j);
          SET_LST_CHR_EL(output,j,i,mkChar(row[j]));
        }
        break;
      }
    }
  }

  // actual number of records fetched
  if(i < num_rec){
    num_rec = i;
    // adjust the length of each of the members in the output_list
    for(j = 0; j<num_fields; j++){
      s_tmp = LST_EL(output,j);
      PROTECT(SET_LENGTH(s_tmp, num_rec));
      SET_ELEMENT(output, j, s_tmp);
      UNPROTECT(1);
    }
  }
  if(completed < 0)
    warning("error while fetching rows");

  result->rowCount += num_rec;
  result->completed = (int) completed;

  UNPROTECT(1);
  return output;
}