<commit_before>#include "dcmqi/TID1500Reader.h"

Json::Value DSRCodedEntryValue2CodeSequence(const DSRCodedEntryValue &value) {
  Json::Value codeSequence;
  codeSequence["CodeValue"] = value.getCodeValue().c_str();
  codeSequence["CodeMeaning"] = value.getCodeMeaning().c_str();
  codeSequence["CodingSchemeDesignator"] = value.getCodingSchemeDesignator().c_str();
  return codeSequence;
}

TID1500Reader::TID1500Reader(const DSRDocumentTree &tree)
  : DSRDocumentTree(tree) {
    // check for expected template identification
    if (!compareTemplateIdentification("1500", "DCMR"))
      CERR << "warning: template identification \"TID 1500 (DCMR)\" not found" << OFendl;

}

Json::Value TID1500Reader::getProcedureReported(){
  Json::Value codeSequence;
  if (gotoNamedNode(CODE_DCM_ProcedureReported)){
    DSRDocumentTreeNodeCursor cursor(getCursor());
    const DSRDocumentTreeNode *node = cursor.getNode();
    codeSequence = DSRCodedEntryValue2CodeSequence(OFstatic_cast(
    const DSRCodeTreeNode *, node)->getValue());
  }
  return codeSequence;
}

Json::Value TID1500Reader::getMeasurements() {
  Json::Value measurements(Json::arrayValue);

  // These modifiers are expected to be defined at the level of measurement group
  std::map<std::string, DSRCodedEntryValue> string2code;
  string2code["activitySession"] = CODE_NCIt_ActivitySession;
  string2code["timePoint"] = CODE_UMLS_TimePoint;
  string2code["measurementMethod"] = CODE_SRT_MeasurementMethod;
  string2code["SourceSeriesForImageSegmentation"] = CODE_DCM_SourceSeriesForSegmentation;
  string2code["TrackingIdentifier"] = CODE_DCM_TrackingIdentifier;
  string2code["TrackingUniqueIdentifier"] = CODE_DCM_TrackingUniqueIdentifier;
  string2code["Finding"] = CODE_DCM_Finding;
  string2code["FindingSite"] = CODE_SRT_FindingSite;

  std::vector<DSRCodedEntryValue> knownConcepts;
  for(std::map<std::string, DSRCodedEntryValue>::const_iterator mIt=string2code.begin();
        mIt!=string2code.end();++mIt){
    knownConcepts.push_back(mIt->second);
  }

  const DSRDocumentTreeNodeCursor cursor(getCursor());

  // iterate over the document tree and read the measurements
  if (gotoNamedNode(CODE_DCM_ImagingMeasurements)) {
    if (gotoNamedChildNode(CODE_DCM_MeasurementGroup)) {
      do {
        // Caveat: we consider only the first measurement group!
        Json::Value measurementGroup;
        // remember cursor to current content item (as a starting point)
        const DSRDocumentTreeNodeCursor groupCursor(getCursor());
        for(std::map<std::string, DSRCodedEntryValue>::const_iterator mIt=string2code.begin();
            mIt!=string2code.end();++mIt){
          Json::Value value = getContentItem(mIt->second, groupCursor);
          if(value!=Json::nullValue)
            measurementGroup[mIt->first] = value;
        }

        initSegmentationContentItems(groupCursor, measurementGroup);

        // details on measurement value(s)
        Json::Value measurementItems(Json::arrayValue);
        Json::Value qualitativeEvaluations(Json::arrayValue);
        DSRDocumentTreeNodeCursor cursor(groupCursor);

        if (cursor.gotoChild()) {
          //size_t counter = 0;
          //COUT << "- Measurements:" << OFendl;
          // iterate over all direct child nodes
          do {
            const DSRDocumentTreeNode *node = cursor.getNode();

            if(node->getConceptName() == CODE_SRT_FindingSite){
              // check if Laterality is present
              DSRDocumentTreeNodeCursor tempCursor(cursor);
              Json::Value laterality = getContentItem(CODE_SRT_Laterality, tempCursor);
              if(laterality!=Json::nullValue)
                measurementGroup["Laterality"] = laterality;
            }

            /* and check for numeric measurement value content items */
            if ((node != NULL) && (node->getValueType() == VT_Num)) {
              //COUT << "  #" << (++counter) << " ";
              //printMeasurement(*OFstatic_cast(const DSRNumTreeNode *, node), cursor);
              Json::Value singleMeasurement = getSingleMeasurement(*OFstatic_cast(const DSRNumTreeNode *, node), cursor);
              measurementItems.append(singleMeasurement);
            } else if (( node != NULL) && (node->getValueType() == VT_Text)) {
              // check if the concept assigned to this item is not in the list of concepts
              // that can be encountered otherwise (same for the below)
              // If not, then conclude this is a qualitative evaluation item

              if(find(knownConcepts.begin(), knownConcepts.end(), node->getConceptName()) == knownConcepts.end()){
                Json::Value singleQualitativeEvaluation;
                singleQualitativeEvaluation["conceptCode"] = DSRCodedEntryValue2CodeSequence(node->getConceptName());
                singleQualitativeEvaluation["conceptValue"] = OFstatic_cast(
                const DSRTextTreeNode *, node)->getValue().c_str();
                qualitativeEvaluations.append(singleQualitativeEvaluation);
              }
            } else if (( node != NULL) && (node->getValueType() == VT_Code)) {
              if(find(knownConcepts.begin(), knownConcepts.end(), node->getConceptName()) == knownConcepts.end()){
                Json::Value singleQualitativeEvaluation;
                singleQualitativeEvaluation["conceptCode"] = DSRCodedEntryValue2CodeSequence(node->getConceptName());
                singleQualitativeEvaluation["conceptValue"] = DSRCodedEntryValue2CodeSequence(OFstatic_cast(
                const DSRCodeTreeNode *, node)->getValue());
                qualitativeEvaluations.append(singleQualitativeEvaluation);
              }
            }
          } while (cursor.gotoNext());

          measurementGroup["measurementItems"] = measurementItems;
          if(qualitativeEvaluations.size())
            measurementGroup["qualitativeEvaluations"] = qualitativeEvaluations;
          measurements.append(measurementGroup);
        }
      } while (gotoNextNamedNode(CODE_DCM_MeasurementGroup, OFFalse /*searchIntoSub*/));
    }
  }
  return measurements;
}

Json::Value TID1500Reader::getContentItem(const DSRCodedEntryValue &conceptName,
                                          DSRDocumentTreeNodeCursor cursor)
{
  Json::Value contentValue;
  // try to go to the given content item
  if (gotoNamedChildNode(conceptName, cursor)) {
    const DSRDocumentTreeNode *node = cursor.getNode();
    if (node != NULL) {
      //COUT << "  - " << conceptName.getCodeMeaning() << ": ";
      // use appropriate value for output
      switch (node->getValueType()) {
        case VT_Text:
          contentValue = OFstatic_cast(
          const DSRTextTreeNode *, node)->getValue().c_str();
          break;
        case VT_UIDRef:
          contentValue = OFstatic_cast(
          const DSRUIDRefTreeNode *, node)->getValue().c_str();
          break;
        case VT_Code:
          contentValue = DSRCodedEntryValue2CodeSequence(OFstatic_cast(
          const DSRCodeTreeNode *, node)->getValue());
          break;
        case VT_Image:
          contentValue = OFstatic_cast(
          const DSRImageTreeNode *, node)->getValue().getSOPInstanceUID().c_str();
          break;
        default:
          COUT << "Error: failed to find content item" << OFendl;
      }
    }
  }
  return contentValue;
}

void TID1500Reader::initSegmentationContentItems(DSRDocumentTreeNodeCursor cursor, Json::Value &json){
  if (gotoNamedChildNode(CODE_DCM_ReferencedSegment, cursor)) {
    const DSRDocumentTreeNode *node = cursor.getNode();
    std::string segmentationUID = OFstatic_cast(
    const DSRImageTreeNode *, node)->getValue().getSOPInstanceUID().c_str();
    OFVector <Uint16> items;
    json["segmentationSOPInstanceUID"] = segmentationUID;
    OFstatic_cast(
    const DSRImageTreeNode *, node)->getValue().getSegmentList().getItems(items);
    if(items.size())
      json["ReferencedSegment"] = items[0];
  }
}

Json::Value TID1500Reader::getSingleMeasurement(const DSRNumTreeNode &numNode,
                                     DSRDocumentTreeNodeCursor cursor) {
  Json::Value singleMeasurement;
  //COUT << numNode.getConceptName().getCodeMeaning() << ": " << numNode.getValue().getNumericValue() << " " << numNode.getValue().getMeasurementUnit().getCodeMeaning() << OFendl;
  singleMeasurement["value"] = numNode.getValue().getNumericValue().c_str();
  singleMeasurement["units"] = DSRCodedEntryValue2CodeSequence(numNode.getMeasurementUnit());
  singleMeasurement["quantity"] = DSRCodedEntryValue2CodeSequence(numNode.getConceptName());

  // check for any modifiers
  if (cursor.gotoChild()) {

    Json::Value measurementModifiers(Json::arrayValue);
    Json::Value derivationParameters(Json::arrayValue);
    Json::Value populationDescription;
    Json::Value measurementNumProperties(Json::arrayValue);

    // iterate over all direct child nodes
    do {
      const DSRDocumentTreeNode *node = cursor.getNode();
      if (node != NULL) {
        if ((node->getRelationshipType() == RT_hasConceptMod) && (node->getValueType() == VT_Code)) {
          //COUT << "     - " << node->getConceptName().getCodeMeaning() << ": " << OFstatic_cast(
          //const DSRCodeTreeNode *, node)->getCodeMeaning() << OFendl;

          // There is only one "Derivation" concept modifier (row 8 in TID1419)
          //  http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_A.html#sect_TID_1419
          // so it has the special treatment
          if (node->getConceptName() == CODE_DCM_Derivation) {
            singleMeasurement["derivationModifier"] = DSRCodedEntryValue2CodeSequence(OFstatic_cast(
            const DSRCodeTreeNode *, node)->getValue());
          } else if (node->getConceptName() == CODE_SRT_FindingSite) {
            CERR << "Warning: For now, FindingSite modifier is interpreted only at the MeasurementGroup level." << OFendl;
          } else if (node->getConceptName() == CODE_SRT_MeasurementMethod) {
            CERR << "Warning: For now, Measurement Method modifier is interpreted only at the MeasurementGroup level." << OFendl;
          } else if (node->getValueType() == VT_Code) {
            // Otherwise, assume that modifier corresponds to row 6.
            // NB: as a consequence, this means other types of concept modifiers must be factored out
            //   and defined at the measurement group level (rows 1-4)
            Json::Value measurementModifier;
            measurementModifier["modifier"] = DSRCodedEntryValue2CodeSequence(node->getConceptName());
            measurementModifier["modifierValue"] = DSRCodedEntryValue2CodeSequence(OFstatic_cast(
            const DSRCodeTreeNode *, node)->getValue());
            measurementModifiers.append(measurementModifier);
          }
        } else if ((node->getRelationshipType() == RT_hasConceptMod) && (node->getValueType() == VT_Text)) {
          if (node->getConceptName() == CODE_DCM_AlgorithmName) {
            singleMeasurement["measurementAlgorithmIdentification"] = Json::Value();
            singleMeasurement["measurementAlgorithmIdentification"]["AlgorithmName"] =
              OFstatic_cast(const DSRTextTreeNode *, node)->getValue().c_str();
          }
          // This node must show up after algorithm name! (and this is required, since
          //   the order is significant in the template)
          if (node->getConceptName() == CODE_DCM_AlgorithmVersion) {
            singleMeasurement["measurementAlgorithmIdentification"]["AlgorithmVersion"] =
              OFstatic_cast(const DSRTextTreeNode *, node)->getValue().c_str();
          }
        }

        // TID1419 is extensible, and thus it is possible incoming document will have other "INFERRED FROM" items,
        //   in which case this heuristic will break.
        // R-INFERRED FROM are not handled
        else if ((node->getRelationshipType() == RT_inferredFrom) && (node->getValueType() == VT_Num)) {
          //COUT << "     - " << node->getConceptName().getCodeMeaning() << ": " << OFstatic_cast(const DSRNumTreeNode *, node)->getNumericValue()
          //    << " " << OFstatic_cast(const DSRNumTreeNode *, node)->getValue().getMeasurementUnit().getCodeMeaning() << OFendl;
          Json::Value derivationParameter;
          derivationParameter["derivationParameter"] = DSRCodedEntryValue2CodeSequence(node->getConceptName());
          derivationParameter["derivationParameterUnits"] = DSRCodedEntryValue2CodeSequence(OFstatic_cast(const DSRNumTreeNode *, node)->getValue().getMeasurementUnit());
          derivationParameter["derivationParameterValue"] = OFstatic_cast(const DSRNumTreeNode *, node)->getNumericValue().c_str();
          derivationParameters.append(derivationParameter);
        }

        else if (node->getRelationshipType() == RT_hasProperties && (node->getValueType() == VT_Text)) {
          if (node->getConceptName() == CODE_DCM_PopulationDescription) {
            populationDescription = OFstatic_cast(const DSRTextTreeNode *, node)->getValue().c_str();
          }
        }

        else if (node->getRelationshipType() == RT_hasProperties && (node->getValueType() == VT_Num)) {
          Json::Value measurementNumProperty;
          measurementNumProperty["numProperty"] = DSRCodedEntryValue2CodeSequence(node->getConceptName());
          measurementNumProperty["numPropertyUnits"] = DSRCodedEntryValue2CodeSequence(OFstatic_cast(const DSRNumTreeNode *, node)->getValue().getMeasurementUnit());
          measurementNumProperty["numPropertyValue"] = OFstatic_cast(const DSRNumTreeNode *, node)->getNumericValue().c_str();
          measurementNumProperties.append(measurementNumProperty);
        }
      }
    } while (cursor.gotoNext());

    if(measurementModifiers.size())
      singleMeasurement["measurementModifiers"] = measurementModifiers;
    if(derivationParameters.size())
      singleMeasurement["measurementDerivationParameters"] = derivationParameters;
    if(populationDescription != 0){
      singleMeasurement["measurementPopulationDescription"] = populationDescription;
    }
    if(measurementNumProperties != "")
      singleMeasurement["measurementNumProperties"] = measurementNumProperties;

  }

  return singleMeasurement;

}

size_t TID1500Reader::gotoNamedChildNode(const DSRCodedEntryValue &conceptName,
                          DSRDocumentTreeNodeCursor &cursor)
{
  size_t nodeID = 0;
  // goto the first child node
  if (conceptName.isValid() && cursor.gotoChild()) {
    const DSRDocumentTreeNode *node;
    // iterate over all nodes on this level
    do {
      node = cursor.getNode();
      // and check for the desired concept name
      if ((node != NULL) && (node->getConceptName() == conceptName))
        nodeID = node->getNodeID();
    } while ((nodeID == 0) && cursor.gotoNext());
  }
  return nodeID;
}
<commit_msg>ENH: remove unnecessary temporary cursor<commit_after>#include "dcmqi/TID1500Reader.h"

Json::Value DSRCodedEntryValue2CodeSequence(const DSRCodedEntryValue &value) {
  Json::Value codeSequence;
  codeSequence["CodeValue"] = value.getCodeValue().c_str();
  codeSequence["CodeMeaning"] = value.getCodeMeaning().c_str();
  codeSequence["CodingSchemeDesignator"] = value.getCodingSchemeDesignator().c_str();
  return codeSequence;
}

TID1500Reader::TID1500Reader(const DSRDocumentTree &tree)
  : DSRDocumentTree(tree) {
    // check for expected template identification
    if (!compareTemplateIdentification("1500", "DCMR"))
      CERR << "warning: template identification \"TID 1500 (DCMR)\" not found" << OFendl;

}

Json::Value TID1500Reader::getProcedureReported(){
  Json::Value codeSequence;
  if (gotoNamedNode(CODE_DCM_ProcedureReported)){
    DSRDocumentTreeNodeCursor cursor(getCursor());
    const DSRDocumentTreeNode *node = cursor.getNode();
    codeSequence = DSRCodedEntryValue2CodeSequence(OFstatic_cast(
    const DSRCodeTreeNode *, node)->getValue());
  }
  return codeSequence;
}

Json::Value TID1500Reader::getMeasurements() {
  Json::Value measurements(Json::arrayValue);

  // These modifiers are expected to be defined at the level of measurement group
  std::map<std::string, DSRCodedEntryValue> string2code;
  string2code["activitySession"] = CODE_NCIt_ActivitySession;
  string2code["timePoint"] = CODE_UMLS_TimePoint;
  string2code["measurementMethod"] = CODE_SRT_MeasurementMethod;
  string2code["SourceSeriesForImageSegmentation"] = CODE_DCM_SourceSeriesForSegmentation;
  string2code["TrackingIdentifier"] = CODE_DCM_TrackingIdentifier;
  string2code["TrackingUniqueIdentifier"] = CODE_DCM_TrackingUniqueIdentifier;
  string2code["Finding"] = CODE_DCM_Finding;
  string2code["FindingSite"] = CODE_SRT_FindingSite;

  std::vector<DSRCodedEntryValue> knownConcepts;
  for(std::map<std::string, DSRCodedEntryValue>::const_iterator mIt=string2code.begin();
        mIt!=string2code.end();++mIt){
    knownConcepts.push_back(mIt->second);
  }

  const DSRDocumentTreeNodeCursor cursor(getCursor());

  // iterate over the document tree and read the measurements
  if (gotoNamedNode(CODE_DCM_ImagingMeasurements)) {
    if (gotoNamedChildNode(CODE_DCM_MeasurementGroup)) {
      do {
        // Caveat: we consider only the first measurement group!
        Json::Value measurementGroup;
        // remember cursor to current content item (as a starting point)
        const DSRDocumentTreeNodeCursor groupCursor(getCursor());
        for(std::map<std::string, DSRCodedEntryValue>::const_iterator mIt=string2code.begin();
            mIt!=string2code.end();++mIt){
          Json::Value value = getContentItem(mIt->second, groupCursor);
          if(value!=Json::nullValue)
            measurementGroup[mIt->first] = value;
        }

        initSegmentationContentItems(groupCursor, measurementGroup);

        // details on measurement value(s)
        Json::Value measurementItems(Json::arrayValue);
        Json::Value qualitativeEvaluations(Json::arrayValue);
        DSRDocumentTreeNodeCursor cursor(groupCursor);

        if (cursor.gotoChild()) {
          //size_t counter = 0;
          //COUT << "- Measurements:" << OFendl;
          // iterate over all direct child nodes
          do {
            const DSRDocumentTreeNode *node = cursor.getNode();

            if(node->getConceptName() == CODE_SRT_FindingSite){
              // check if Laterality is present
              Json::Value laterality = getContentItem(CODE_SRT_Laterality, cursor);
              if(laterality!=Json::nullValue)
                measurementGroup["Laterality"] = laterality;
            }

            /* and check for numeric measurement value content items */
            if ((node != NULL) && (node->getValueType() == VT_Num)) {
              //COUT << "  #" << (++counter) << " ";
              //printMeasurement(*OFstatic_cast(const DSRNumTreeNode *, node), cursor);
              Json::Value singleMeasurement = getSingleMeasurement(*OFstatic_cast(const DSRNumTreeNode *, node), cursor);
              measurementItems.append(singleMeasurement);
            } else if (( node != NULL) && (node->getValueType() == VT_Text)) {
              // check if the concept assigned to this item is not in the list of concepts
              // that can be encountered otherwise (same for the below)
              // If not, then conclude this is a qualitative evaluation item

              if(find(knownConcepts.begin(), knownConcepts.end(), node->getConceptName()) == knownConcepts.end()){
                Json::Value singleQualitativeEvaluation;
                singleQualitativeEvaluation["conceptCode"] = DSRCodedEntryValue2CodeSequence(node->getConceptName());
                singleQualitativeEvaluation["conceptValue"] = OFstatic_cast(
                const DSRTextTreeNode *, node)->getValue().c_str();
                qualitativeEvaluations.append(singleQualitativeEvaluation);
              }
            } else if (( node != NULL) && (node->getValueType() == VT_Code)) {
              if(find(knownConcepts.begin(), knownConcepts.end(), node->getConceptName()) == knownConcepts.end()){
                Json::Value singleQualitativeEvaluation;
                singleQualitativeEvaluation["conceptCode"] = DSRCodedEntryValue2CodeSequence(node->getConceptName());
                singleQualitativeEvaluation["conceptValue"] = DSRCodedEntryValue2CodeSequence(OFstatic_cast(
                const DSRCodeTreeNode *, node)->getValue());
                qualitativeEvaluations.append(singleQualitativeEvaluation);
              }
            }
          } while (cursor.gotoNext());

          measurementGroup["measurementItems"] = measurementItems;
          if(qualitativeEvaluations.size())
            measurementGroup["qualitativeEvaluations"] = qualitativeEvaluations;
          measurements.append(measurementGroup);
        }
      } while (gotoNextNamedNode(CODE_DCM_MeasurementGroup, OFFalse /*searchIntoSub*/));
    }
  }
  return measurements;
}

Json::Value TID1500Reader::getContentItem(const DSRCodedEntryValue &conceptName,
                                          DSRDocumentTreeNodeCursor cursor)
{
  Json::Value contentValue;
  // try to go to the given content item
  if (gotoNamedChildNode(conceptName, cursor)) {
    const DSRDocumentTreeNode *node = cursor.getNode();
    if (node != NULL) {
      //COUT << "  - " << conceptName.getCodeMeaning() << ": ";
      // use appropriate value for output
      switch (node->getValueType()) {
        case VT_Text:
          contentValue = OFstatic_cast(
          const DSRTextTreeNode *, node)->getValue().c_str();
          break;
        case VT_UIDRef:
          contentValue = OFstatic_cast(
          const DSRUIDRefTreeNode *, node)->getValue().c_str();
          break;
        case VT_Code:
          contentValue = DSRCodedEntryValue2CodeSequence(OFstatic_cast(
          const DSRCodeTreeNode *, node)->getValue());
          break;
        case VT_Image:
          contentValue = OFstatic_cast(
          const DSRImageTreeNode *, node)->getValue().getSOPInstanceUID().c_str();
          break;
        default:
          COUT << "Error: failed to find content item" << OFendl;
      }
    }
  }
  return contentValue;
}

void TID1500Reader::initSegmentationContentItems(DSRDocumentTreeNodeCursor cursor, Json::Value &json){
  if (gotoNamedChildNode(CODE_DCM_ReferencedSegment, cursor)) {
    const DSRDocumentTreeNode *node = cursor.getNode();
    std::string segmentationUID = OFstatic_cast(
    const DSRImageTreeNode *, node)->getValue().getSOPInstanceUID().c_str();
    OFVector <Uint16> items;
    json["segmentationSOPInstanceUID"] = segmentationUID;
    OFstatic_cast(
    const DSRImageTreeNode *, node)->getValue().getSegmentList().getItems(items);
    if(items.size())
      json["ReferencedSegment"] = items[0];
  }
}

Json::Value TID1500Reader::getSingleMeasurement(const DSRNumTreeNode &numNode,
                                     DSRDocumentTreeNodeCursor cursor) {
  Json::Value singleMeasurement;
  //COUT << numNode.getConceptName().getCodeMeaning() << ": " << numNode.getValue().getNumericValue() << " " << numNode.getValue().getMeasurementUnit().getCodeMeaning() << OFendl;
  singleMeasurement["value"] = numNode.getValue().getNumericValue().c_str();
  singleMeasurement["units"] = DSRCodedEntryValue2CodeSequence(numNode.getMeasurementUnit());
  singleMeasurement["quantity"] = DSRCodedEntryValue2CodeSequence(numNode.getConceptName());

  // check for any modifiers
  if (cursor.gotoChild()) {

    Json::Value measurementModifiers(Json::arrayValue);
    Json::Value derivationParameters(Json::arrayValue);
    Json::Value populationDescription;
    Json::Value measurementNumProperties(Json::arrayValue);

    // iterate over all direct child nodes
    do {
      const DSRDocumentTreeNode *node = cursor.getNode();
      if (node != NULL) {
        if ((node->getRelationshipType() == RT_hasConceptMod) && (node->getValueType() == VT_Code)) {
          //COUT << "     - " << node->getConceptName().getCodeMeaning() << ": " << OFstatic_cast(
          //const DSRCodeTreeNode *, node)->getCodeMeaning() << OFendl;

          // There is only one "Derivation" concept modifier (row 8 in TID1419)
          //  http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_A.html#sect_TID_1419
          // so it has the special treatment
          if (node->getConceptName() == CODE_DCM_Derivation) {
            singleMeasurement["derivationModifier"] = DSRCodedEntryValue2CodeSequence(OFstatic_cast(
            const DSRCodeTreeNode *, node)->getValue());
          } else if (node->getConceptName() == CODE_SRT_FindingSite) {
            CERR << "Warning: For now, FindingSite modifier is interpreted only at the MeasurementGroup level." << OFendl;
          } else if (node->getConceptName() == CODE_SRT_MeasurementMethod) {
            CERR << "Warning: For now, Measurement Method modifier is interpreted only at the MeasurementGroup level." << OFendl;
          } else if (node->getValueType() == VT_Code) {
            // Otherwise, assume that modifier corresponds to row 6.
            // NB: as a consequence, this means other types of concept modifiers must be factored out
            //   and defined at the measurement group level (rows 1-4)
            Json::Value measurementModifier;
            measurementModifier["modifier"] = DSRCodedEntryValue2CodeSequence(node->getConceptName());
            measurementModifier["modifierValue"] = DSRCodedEntryValue2CodeSequence(OFstatic_cast(
            const DSRCodeTreeNode *, node)->getValue());
            measurementModifiers.append(measurementModifier);
          }
        } else if ((node->getRelationshipType() == RT_hasConceptMod) && (node->getValueType() == VT_Text)) {
          if (node->getConceptName() == CODE_DCM_AlgorithmName) {
            singleMeasurement["measurementAlgorithmIdentification"] = Json::Value();
            singleMeasurement["measurementAlgorithmIdentification"]["AlgorithmName"] =
              OFstatic_cast(const DSRTextTreeNode *, node)->getValue().c_str();
          }
          // This node must show up after algorithm name! (and this is required, since
          //   the order is significant in the template)
          if (node->getConceptName() == CODE_DCM_AlgorithmVersion) {
            singleMeasurement["measurementAlgorithmIdentification"]["AlgorithmVersion"] =
              OFstatic_cast(const DSRTextTreeNode *, node)->getValue().c_str();
          }
        }

        // TID1419 is extensible, and thus it is possible incoming document will have other "INFERRED FROM" items,
        //   in which case this heuristic will break.
        // R-INFERRED FROM are not handled
        else if ((node->getRelationshipType() == RT_inferredFrom) && (node->getValueType() == VT_Num)) {
          //COUT << "     - " << node->getConceptName().getCodeMeaning() << ": " << OFstatic_cast(const DSRNumTreeNode *, node)->getNumericValue()
          //    << " " << OFstatic_cast(const DSRNumTreeNode *, node)->getValue().getMeasurementUnit().getCodeMeaning() << OFendl;
          Json::Value derivationParameter;
          derivationParameter["derivationParameter"] = DSRCodedEntryValue2CodeSequence(node->getConceptName());
          derivationParameter["derivationParameterUnits"] = DSRCodedEntryValue2CodeSequence(OFstatic_cast(const DSRNumTreeNode *, node)->getValue().getMeasurementUnit());
          derivationParameter["derivationParameterValue"] = OFstatic_cast(const DSRNumTreeNode *, node)->getNumericValue().c_str();
          derivationParameters.append(derivationParameter);
        }

        else if (node->getRelationshipType() == RT_hasProperties && (node->getValueType() == VT_Text)) {
          if (node->getConceptName() == CODE_DCM_PopulationDescription) {
            populationDescription = OFstatic_cast(const DSRTextTreeNode *, node)->getValue().c_str();
          }
        }

        else if (node->getRelationshipType() == RT_hasProperties && (node->getValueType() == VT_Num)) {
          Json::Value measurementNumProperty;
          measurementNumProperty["numProperty"] = DSRCodedEntryValue2CodeSequence(node->getConceptName());
          measurementNumProperty["numPropertyUnits"] = DSRCodedEntryValue2CodeSequence(OFstatic_cast(const DSRNumTreeNode *, node)->getValue().getMeasurementUnit());
          measurementNumProperty["numPropertyValue"] = OFstatic_cast(const DSRNumTreeNode *, node)->getNumericValue().c_str();
          measurementNumProperties.append(measurementNumProperty);
        }
      }
    } while (cursor.gotoNext());

    if(measurementModifiers.size())
      singleMeasurement["measurementModifiers"] = measurementModifiers;
    if(derivationParameters.size())
      singleMeasurement["measurementDerivationParameters"] = derivationParameters;
    if(populationDescription != 0){
      singleMeasurement["measurementPopulationDescription"] = populationDescription;
    }
    if(measurementNumProperties != "")
      singleMeasurement["measurementNumProperties"] = measurementNumProperties;

  }

  return singleMeasurement;

}

size_t TID1500Reader::gotoNamedChildNode(const DSRCodedEntryValue &conceptName,
                          DSRDocumentTreeNodeCursor &cursor)
{
  size_t nodeID = 0;
  // goto the first child node
  if (conceptName.isValid() && cursor.gotoChild()) {
    const DSRDocumentTreeNode *node;
    // iterate over all nodes on this level
    do {
      node = cursor.getNode();
      // and check for the desired concept name
      if ((node != NULL) && (node->getConceptName() == conceptName))
        nodeID = node->getNodeID();
    } while ((nodeID == 0) && cursor.gotoNext());
  }
  return nodeID;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <iostream>
#include <string>
#include <cstdlib>
#include <fstream>
#include <vector>
#include <cmath>
#include <sstream>
#include <stdio.h>
#include <unistd.h>
using namespace std;

#include "Command.h"
#include "Sentinel.h"

Sentinel::Sentinel()
{
    first = 0;
    second = 0;
}

Sentinel::Sentinel(Base* first, Base* second)
{
    this->first = first;
    this->second = second;
}

Sentinel::Sentinel(Base* first, Command* second)
{
    this->first = first;
    this->second = second;
}

Sentinel::~Sentinel()
{
    delete first;
    delete second;
}<commit_msg>Delete Sentinel.cpp<commit_after><|endoftext|>


<commit_before>/*
 * Main application window
 *
 * This file is part of softrig, a simple software defined radio transceiver.
 *
 * Copyright 2017 Alexandru Csete OZ9AEC.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#include <QDebug>
#include <QtWidgets>

#include "app/sdr_thread.h"
#include "gui/control_panel.h"
#include "gui/device_config.h"
#include "gui/freq_ctrl.h"
#include "gui/ssi_widget.h"

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "gui/tmp_plotter.h"

// IDs used to identify menu items
#define MENU_ID_SDR         0
#define MENU_ID_AUDIO       1
#define MENU_ID_GUI         2

#define DEFAULT_FREQ        127100000

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    QWidget   *spacer1;
    QWidget   *spacer2;
    QWidget   *spacer3;

    ui->setupUi(this);
    ui->menuBar->hide();
    ui->toolBar->hide();

    sdr = new SdrThread();

    fft_timer = new QTimer(this);
    connect(fft_timer, SIGNAL(timeout()), this, SLOT(fftTimeout()));
    fft_data = new real_t[FFT_SIZE]; // FIXME
    fft_avg = new real_t[FFT_SIZE];

    // 3 horizontal spacers
    spacer1 = new QWidget();
    spacer1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    spacer2 = new QWidget();
    spacer2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    spacer3 = new QWidget();
    spacer3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    createButtons();

    // Frequency controller
    fctl = new FreqCtrl(this);
    fctl->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    fctl->setup(10, 0, 2e9, 1, FCTL_UNIT_NONE);
    fctl->setFrequency(DEFAULT_FREQ);
    connect(fctl, SIGNAL(newFrequency(qint64)), this,
            SLOT(newFrequency(qint64)));

    // SSI
    smeter = new SsiWidget(this);
    smeter->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    // Control panel
    cpanel = new ControlPanel(this);
    connect(cpanel, SIGNAL(runButtonClicked(bool)),
            this, SLOT(runButtonClicked(bool)));
    connect(cpanel, SIGNAL(demodChanged(sdr_demod_t)),
            this, SLOT(setDemod(sdr_demod_t)));
    connect(cpanel, SIGNAL(filterChanged(float,float)),
            this, SLOT(setFilter(float,float)));
    connect(cpanel, SIGNAL(cwOffsetChanged(float)),
            this, SLOT(setCwOffset(float)));

    // Temporary FFT plot
    fft_plot = new CPlotter(this);
    fft_plot->setSampleRate(3000000.0);
    fft_plot->setSpanFreq(3000000);
    fft_plot->setCenterFreq(DEFAULT_FREQ);
    fft_plot->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    fft_plot->setFftRange(-100.0, 0.0);
    connect(fft_plot, SIGNAL(newCenterFreq(qint64)),
            this, SLOT(newPlotterCenterFreq(qint64)));
    connect(fft_plot, SIGNAL(pandapterRangeChanged(float,float)),
            fft_plot, SLOT(setWaterfallRange(float,float)));

    // top layout with frequency controller, meter and buttons
    top_layout = new QHBoxLayout();
    top_layout->addWidget(ptt_button, 0);
    top_layout->addWidget(spacer1, 1);
    top_layout->addWidget(fctl, 2);
    top_layout->addWidget(spacer2, 1);
    top_layout->addWidget(smeter, 2);
    top_layout->addWidget(spacer3, 1);
    top_layout->addWidget(cfg_button, 0);

    // main layout with FFT and control panel
    main_layout = new QVBoxLayout();
    main_layout->addLayout(top_layout, 0);
    main_layout->addWidget(fft_plot, 1);

    // top level window layout
    win_layout = new QHBoxLayout();
    win_layout->setContentsMargins(0, 4, 0, 0);
    win_layout->setSpacing(2);
    win_layout->addLayout(main_layout, 12);
    win_layout->addWidget(cpanel, 2);
    ui->centralWidget->setLayout(win_layout);

    // FIXME: Adjust default size as a function of desktop size
}

MainWindow::~MainWindow()
{
    // stop SDR
    runButtonClicked(false);

    delete sdr;
    delete fft_data;
    delete fft_avg;

    delete cfg_menu;
    delete cfg_button;
    delete ptt_button;

    delete fctl;
    delete smeter;
    delete fft_plot;
    delete cpanel;
    delete top_layout;
    delete main_layout;
    delete win_layout;
    delete ui;
}

void MainWindow::createButtons(void)
{
    ptt_button = new QToolButton(this);
    ptt_button->setText(tr("PTT"));
    ptt_button->setCheckable(true);
    ptt_button->setMinimumSize(36, 36);
    ptt_button->setSizePolicy(QSizePolicy::MinimumExpanding,
                              QSizePolicy::MinimumExpanding);

    {
        QAction     *action;

        cfg_menu = new QMenu();
        cfg_menu->setTitle(tr("Configure..."));
        action = cfg_menu->addAction(tr("SDR device"));
        action->setData(QVariant((int)MENU_ID_SDR));
        action = cfg_menu->addAction(tr("Soundcard"));
        action->setData(QVariant((int)MENU_ID_AUDIO));
        action = cfg_menu->addAction(tr("User interface"));
        action->setData(QVariant((int)MENU_ID_GUI));
    }

    cfg_button = new QToolButton(this);
    cfg_button->setText("C");
    cfg_button->setMinimumSize(36, 36);
    cfg_button->setMenu(cfg_menu);
    cfg_button->setSizePolicy(QSizePolicy::MinimumExpanding,
                              QSizePolicy::MinimumExpanding);
    connect(cfg_button, SIGNAL(triggered(QAction *)),
            this, SLOT(menuActivated(QAction *)));
    connect(cfg_button, SIGNAL(clicked(bool)),
            this, SLOT(cfgButtonClicked(bool)));
}

void MainWindow::runButtonClicked(bool checked)
{
    if (checked)
    {
        if (sdr->start() == SDR_THREAD_OK)
        {
            newFrequency(fctl->getFrequency());
            fft_timer->start(50);

            {
                int i;
                for (i = 0; i < FFT_SIZE; i++)
                    fft_avg[i] = -100.0;
            }
        }
        // else FIXME
    }
    else
    {
        fft_timer->stop();
        sdr->stop();
    }
}

void MainWindow::cfgButtonClicked(bool checked)
{
    Q_UNUSED(checked);
    cpanel->setVisible(!cpanel->isVisible());
}

void MainWindow::runDeviceConfig(void)
{
    DeviceConfig    conf(this);
    conf.exec();
}

void MainWindow::menuActivated(QAction *action)
{
    bool    conv_ok;
    int     menu_id;

    menu_id = action->data().toInt(&conv_ok);
    if (!conv_ok)
    {
        qCritical("%s: Menu item '%s' has no valid ID", __func__,
                  action->text().toLatin1().data());
        return;
    }

    switch (menu_id)
    {
    case MENU_ID_SDR:
        runDeviceConfig();
        break;
    case MENU_ID_AUDIO:
        break;
    case MENU_ID_GUI:
        break;
    default:
        qCritical("%s: Unknown menu item '%s' ID=%d", __func__,
                  action->text().toLatin1().data(), menu_id);
        break;
    }
}

void MainWindow::newFrequency(qint64 freq)
{
    sdr->setRxFrequency(freq);
    fft_plot->setCenterFreq(freq);
}

void MainWindow::newPlotterCenterFreq(qint64 freq)
{
    fctl->setFrequency(freq);
}

void MainWindow::setDemod(sdr_demod_t demod)
{
    sdr->setDemod(demod);
}

void MainWindow::setFilter(real_t low_cut, real_t high_cut)
{
    sdr->setRxFilter(low_cut, high_cut);
    fft_plot->setHiLowCutFrequencies(low_cut, high_cut);
}

void MainWindow::setCwOffset(real_t offset)
{
    sdr->setRxCwOffset(offset);
}

void MainWindow::fftTimeout(void)
{
    quint32    fft_samples;

    fft_samples = sdr->getFftData(fft_data);
    if (fft_samples == FFT_SIZE)
    {
        int i;
        for (i = 0; i < FFT_SIZE; i++)
            fft_avg[i] += 0.5f * (fft_data[i] - fft_avg[i]);

        fft_plot->setNewFttData(fft_avg, fft_data, fft_samples);
    }

    // FIXME
    smeter->setLevel(sdr->getSignalStrength());
}
<commit_msg>Hide the status bar<commit_after>/*
 * Main application window
 *
 * This file is part of softrig, a simple software defined radio transceiver.
 *
 * Copyright 2017 Alexandru Csete OZ9AEC.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#include <QDebug>
#include <QtWidgets>

#include "app/sdr_thread.h"
#include "gui/control_panel.h"
#include "gui/device_config.h"
#include "gui/freq_ctrl.h"
#include "gui/ssi_widget.h"

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "gui/tmp_plotter.h"

// IDs used to identify menu items
#define MENU_ID_SDR         0
#define MENU_ID_AUDIO       1
#define MENU_ID_GUI         2

#define DEFAULT_FREQ        127100000

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    QWidget   *spacer1;
    QWidget   *spacer2;
    QWidget   *spacer3;

    ui->setupUi(this);
    ui->menuBar->hide();
    ui->toolBar->hide();
    ui->statusBar->hide();

    sdr = new SdrThread();

    fft_timer = new QTimer(this);
    connect(fft_timer, SIGNAL(timeout()), this, SLOT(fftTimeout()));
    fft_data = new real_t[FFT_SIZE]; // FIXME
    fft_avg = new real_t[FFT_SIZE];

    // 3 horizontal spacers
    spacer1 = new QWidget();
    spacer1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    spacer2 = new QWidget();
    spacer2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    spacer3 = new QWidget();
    spacer3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    createButtons();

    // Frequency controller
    fctl = new FreqCtrl(this);
    fctl->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    fctl->setup(10, 0, 2e9, 1, FCTL_UNIT_NONE);
    fctl->setFrequency(DEFAULT_FREQ);
    connect(fctl, SIGNAL(newFrequency(qint64)), this,
            SLOT(newFrequency(qint64)));

    // SSI
    smeter = new SsiWidget(this);
    smeter->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    // Control panel
    cpanel = new ControlPanel(this);
    connect(cpanel, SIGNAL(runButtonClicked(bool)),
            this, SLOT(runButtonClicked(bool)));
    connect(cpanel, SIGNAL(demodChanged(sdr_demod_t)),
            this, SLOT(setDemod(sdr_demod_t)));
    connect(cpanel, SIGNAL(filterChanged(float,float)),
            this, SLOT(setFilter(float,float)));
    connect(cpanel, SIGNAL(cwOffsetChanged(float)),
            this, SLOT(setCwOffset(float)));

    // Temporary FFT plot
    fft_plot = new CPlotter(this);
    fft_plot->setSampleRate(3000000.0);
    fft_plot->setSpanFreq(3000000);
    fft_plot->setCenterFreq(DEFAULT_FREQ);
    fft_plot->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    fft_plot->setFftRange(-100.0, 0.0);
    connect(fft_plot, SIGNAL(newCenterFreq(qint64)),
            this, SLOT(newPlotterCenterFreq(qint64)));
    connect(fft_plot, SIGNAL(pandapterRangeChanged(float,float)),
            fft_plot, SLOT(setWaterfallRange(float,float)));

    // top layout with frequency controller, meter and buttons
    top_layout = new QHBoxLayout();
    top_layout->addWidget(ptt_button, 0);
    top_layout->addWidget(spacer1, 1);
    top_layout->addWidget(fctl, 2);
    top_layout->addWidget(spacer2, 1);
    top_layout->addWidget(smeter, 2);
    top_layout->addWidget(spacer3, 1);
    top_layout->addWidget(cfg_button, 0);

    // main layout with FFT and control panel
    main_layout = new QVBoxLayout();
    main_layout->addLayout(top_layout, 0);
    main_layout->addWidget(fft_plot, 1);

    // top level window layout
    win_layout = new QHBoxLayout();
    win_layout->setContentsMargins(0, 4, 0, 0);
    win_layout->setSpacing(2);
    win_layout->addLayout(main_layout, 12);
    win_layout->addWidget(cpanel, 2);
    ui->centralWidget->setLayout(win_layout);

    // FIXME: Adjust default size as a function of desktop size
}

MainWindow::~MainWindow()
{
    // stop SDR
    runButtonClicked(false);

    delete sdr;
    delete fft_data;
    delete fft_avg;

    delete cfg_menu;
    delete cfg_button;
    delete ptt_button;

    delete fctl;
    delete smeter;
    delete fft_plot;
    delete cpanel;
    delete top_layout;
    delete main_layout;
    delete win_layout;
    delete ui;
}

void MainWindow::createButtons(void)
{
    ptt_button = new QToolButton(this);
    ptt_button->setText(tr("PTT"));
    ptt_button->setCheckable(true);
    ptt_button->setMinimumSize(36, 36);
    ptt_button->setSizePolicy(QSizePolicy::MinimumExpanding,
                              QSizePolicy::MinimumExpanding);

    {
        QAction     *action;

        cfg_menu = new QMenu();
        cfg_menu->setTitle(tr("Configure..."));
        action = cfg_menu->addAction(tr("SDR device"));
        action->setData(QVariant((int)MENU_ID_SDR));
        action = cfg_menu->addAction(tr("Soundcard"));
        action->setData(QVariant((int)MENU_ID_AUDIO));
        action = cfg_menu->addAction(tr("User interface"));
        action->setData(QVariant((int)MENU_ID_GUI));
    }

    cfg_button = new QToolButton(this);
    cfg_button->setText("C");
    cfg_button->setMinimumSize(36, 36);
    cfg_button->setMenu(cfg_menu);
    cfg_button->setSizePolicy(QSizePolicy::MinimumExpanding,
                              QSizePolicy::MinimumExpanding);
    connect(cfg_button, SIGNAL(triggered(QAction *)),
            this, SLOT(menuActivated(QAction *)));
    connect(cfg_button, SIGNAL(clicked(bool)),
            this, SLOT(cfgButtonClicked(bool)));
}

void MainWindow::runButtonClicked(bool checked)
{
    if (checked)
    {
        if (sdr->start() == SDR_THREAD_OK)
        {
            newFrequency(fctl->getFrequency());
            fft_timer->start(50);

            {
                int i;
                for (i = 0; i < FFT_SIZE; i++)
                    fft_avg[i] = -100.0;
            }
        }
        // else FIXME
    }
    else
    {
        fft_timer->stop();
        sdr->stop();
    }
}

void MainWindow::cfgButtonClicked(bool checked)
{
    Q_UNUSED(checked);
    cpanel->setVisible(!cpanel->isVisible());
}

void MainWindow::runDeviceConfig(void)
{
    DeviceConfig    conf(this);
    conf.exec();
}

void MainWindow::menuActivated(QAction *action)
{
    bool    conv_ok;
    int     menu_id;

    menu_id = action->data().toInt(&conv_ok);
    if (!conv_ok)
    {
        qCritical("%s: Menu item '%s' has no valid ID", __func__,
                  action->text().toLatin1().data());
        return;
    }

    switch (menu_id)
    {
    case MENU_ID_SDR:
        runDeviceConfig();
        break;
    case MENU_ID_AUDIO:
        break;
    case MENU_ID_GUI:
        break;
    default:
        qCritical("%s: Unknown menu item '%s' ID=%d", __func__,
                  action->text().toLatin1().data(), menu_id);
        break;
    }
}

void MainWindow::newFrequency(qint64 freq)
{
    sdr->setRxFrequency(freq);
    fft_plot->setCenterFreq(freq);
}

void MainWindow::newPlotterCenterFreq(qint64 freq)
{
    fctl->setFrequency(freq);
}

void MainWindow::setDemod(sdr_demod_t demod)
{
    sdr->setDemod(demod);
}

void MainWindow::setFilter(real_t low_cut, real_t high_cut)
{
    sdr->setRxFilter(low_cut, high_cut);
    fft_plot->setHiLowCutFrequencies(low_cut, high_cut);
}

void MainWindow::setCwOffset(real_t offset)
{
    sdr->setRxCwOffset(offset);
}

void MainWindow::fftTimeout(void)
{
    quint32    fft_samples;

    fft_samples = sdr->getFftData(fft_data);
    if (fft_samples == FFT_SIZE)
    {
        int i;
        for (i = 0; i < FFT_SIZE; i++)
            fft_avg[i] += 0.5f * (fft_data[i] - fft_avg[i]);

        fft_plot->setNewFttData(fft_avg, fft_data, fft_samples);
    }

    // FIXME
    smeter->setLevel(sdr->getSignalStrength());
}
<|endoftext|>


<commit_before>#include "server_https.hpp"
#include "client_https.hpp"

//Added for the json-example
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

//Added for the default_resource example
#include<fstream>

using namespace std;
using namespace SimpleWeb;
//Added for the json-example:
using namespace boost::property_tree;

int main() {
    //HTTPS-server at port 8080 using 4 threads
    Server<HTTPS> server(8080, 4, "server.crt", "server.key");

    //Add resources using regular expression for path, a method-string, and an anonymous function
    //POST-example for the path /string, responds the posted string
    //  If C++14: use 'auto' instead of 'shared_ptr<Server<HTTPS>::Request>'
    server.resource["^/string/?$"]["POST"]=[](ostream& response, shared_ptr<Server<HTTPS>::Request> request) {
        //Retrieve string from istream (*request.content)
        stringstream ss;
        request->content >> ss.rdbuf();
        string content=ss.str();

        response << "HTTP/1.1 200 OK\r\nContent-Length: " << content.length() << "\r\n\r\n" << content;
    };

    //POST-example for the path /json, responds firstName+" "+lastName from the posted json
    //Responds with an appropriate error message if the posted json is not valid, or if firstName or lastName is missing
    //Example posted json:
    //{
    //  "firstName": "John",
    //  "lastName": "Smith",
    //  "age": 25
    //}
    server.resource["^/json/?$"]["POST"]=[](ostream& response, shared_ptr<Server<HTTPS>::Request> request) {
        try {
            ptree pt;
            read_json(request->content, pt);

            string name=pt.get<string>("firstName")+" "+pt.get<string>("lastName");

            response << "HTTP/1.1 200 OK\r\nContent-Length: " << name.length() << "\r\n\r\n" << name;
        }
        catch(exception& e) {
            response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << strlen(e.what()) << "\r\n\r\n" << e.what();
        }
    };

    //GET-example for the path /info
    //Responds with request-information
    server.resource["^/info/?$"]["GET"]=[](ostream& response, shared_ptr<Server<HTTPS>::Request> request) {
        stringstream content_stream;
        content_stream << "
Request:
";
        content_stream << request->method << " " << request->path << " HTTP/" << request->http_version << "
";
        for(auto& header: request->header) {
            content_stream << header.first << ": " << header.second << "
";
        }

        //find length of content_stream (length received using content_stream.tellp())
        content_stream.seekp(0, ios::end);

        response <<  "HTTP/1.1 200 OK\r\nContent-Length: " << content_stream.tellp() << "\r\n\r\n" << content_stream.rdbuf();
    };

    //GET-example for the path /match/[number], responds with the matched string in path (number)
    //For instance a request GET /match/123 will receive: 123
    server.resource["^/match/([0-9]+)/?$"]["GET"]=[](ostream& response, shared_ptr<Server<HTTPS>::Request> request) {
        string number=request->path_match[1];
        response << "HTTP/1.1 200 OK\r\nContent-Length: " << number.length() << "\r\n\r\n" << number;
    };

    //Default GET-example. If no other matches, this anonymous function will be called.
    //Will respond with content in the web/-directory, and its subdirectories.
    //Default file: index.html
    //Can for instance be used to retrieve an HTML 5 client that uses REST-resources on this server
    server.default_resource["^/?(.*)$"]["GET"]=[](ostream& response, shared_ptr<Server<HTTPS>::Request> request) {
        string filename="web/";

        string path=request->path_match[1];

        //Replace all ".." with "." (so we can't leave the web-directory)
        size_t pos;
        while((pos=path.find(".."))!=string::npos) {
            path.erase(pos, 1);
        }

        filename+=path;
        ifstream ifs;
        //A simple platform-independent file-or-directory check do not exist, but this works in most of the cases:
        if(filename.find('.')==string::npos) {
            if(filename[filename.length()-1]!='/')
                filename+='/';
            filename+="index.html";
        }
        ifs.open(filename, ifstream::in);

        if(ifs) {
            ifs.seekg(0, ios::end);
            size_t length=ifs.tellg();

            ifs.seekg(0, ios::beg);

            //The file-content is copied to the response-stream. Should not be used for very large files.
            response << "HTTP/1.1 200 OK\r\nContent-Length: " << length << "\r\n\r\n" << ifs.rdbuf();

            ifs.close();
        }
        else {
            string content="Could not open file "+filename;
            response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << content.length() << "\r\n\r\n" << content;
        }
    };

    thread server_thread([&server](){
        //Start WS-server
        server.start();
    });

    //Wait for server to start so that the client can connect
    this_thread::sleep_for(chrono::seconds(1));

    //Client examples
    //Second Client() parameter set to false: no certificate verification
    Client<HTTPS> client("localhost:8080", false);
    auto r1=client.request("GET", "/match/123");
    cout << r1->content.rdbuf() << endl;

    string json="{\"firstName\": \"John\",\"lastName\": \"Smith\",\"age\": 25}";
    stringstream ss(json);
    auto r2=client.request("POST", "/string", ss);
    cout << r2->content.rdbuf() << endl;

    ss.str(json);
    auto r3=client.request("POST", "/json", ss);
    cout << r3->content.rdbuf() << endl;

    server_thread.join();

    return 0;
}<commit_msg>fixed comment<commit_after>#include "server_https.hpp"
#include "client_https.hpp"

//Added for the json-example
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

//Added for the default_resource example
#include<fstream>

using namespace std;
using namespace SimpleWeb;
//Added for the json-example:
using namespace boost::property_tree;

int main() {
    //HTTPS-server at port 8080 using 4 threads
    Server<HTTPS> server(8080, 4, "server.crt", "server.key");

    //Add resources using regular expression for path, a method-string, and an anonymous function
    //POST-example for the path /string, responds the posted string
    //  If C++14: use 'auto' instead of 'shared_ptr<Server<HTTPS>::Request>'
    server.resource["^/string/?$"]["POST"]=[](ostream& response, shared_ptr<Server<HTTPS>::Request> request) {
        //Retrieve string from istream (*request.content)
        stringstream ss;
        request->content >> ss.rdbuf();
        string content=ss.str();

        response << "HTTP/1.1 200 OK\r\nContent-Length: " << content.length() << "\r\n\r\n" << content;
    };

    //POST-example for the path /json, responds firstName+" "+lastName from the posted json
    //Responds with an appropriate error message if the posted json is not valid, or if firstName or lastName is missing
    //Example posted json:
    //{
    //  "firstName": "John",
    //  "lastName": "Smith",
    //  "age": 25
    //}
    server.resource["^/json/?$"]["POST"]=[](ostream& response, shared_ptr<Server<HTTPS>::Request> request) {
        try {
            ptree pt;
            read_json(request->content, pt);

            string name=pt.get<string>("firstName")+" "+pt.get<string>("lastName");

            response << "HTTP/1.1 200 OK\r\nContent-Length: " << name.length() << "\r\n\r\n" << name;
        }
        catch(exception& e) {
            response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << strlen(e.what()) << "\r\n\r\n" << e.what();
        }
    };

    //GET-example for the path /info
    //Responds with request-information
    server.resource["^/info/?$"]["GET"]=[](ostream& response, shared_ptr<Server<HTTPS>::Request> request) {
        stringstream content_stream;
        content_stream << "
Request:
";
        content_stream << request->method << " " << request->path << " HTTP/" << request->http_version << "
";
        for(auto& header: request->header) {
            content_stream << header.first << ": " << header.second << "
";
        }

        //find length of content_stream (length received using content_stream.tellp())
        content_stream.seekp(0, ios::end);

        response <<  "HTTP/1.1 200 OK\r\nContent-Length: " << content_stream.tellp() << "\r\n\r\n" << content_stream.rdbuf();
    };

    //GET-example for the path /match/[number], responds with the matched string in path (number)
    //For instance a request GET /match/123 will receive: 123
    server.resource["^/match/([0-9]+)/?$"]["GET"]=[](ostream& response, shared_ptr<Server<HTTPS>::Request> request) {
        string number=request->path_match[1];
        response << "HTTP/1.1 200 OK\r\nContent-Length: " << number.length() << "\r\n\r\n" << number;
    };

    //Default GET-example. If no other matches, this anonymous function will be called.
    //Will respond with content in the web/-directory, and its subdirectories.
    //Default file: index.html
    //Can for instance be used to retrieve an HTML 5 client that uses REST-resources on this server
    server.default_resource["^/?(.*)$"]["GET"]=[](ostream& response, shared_ptr<Server<HTTPS>::Request> request) {
        string filename="web/";

        string path=request->path_match[1];

        //Replace all ".." with "." (so we can't leave the web-directory)
        size_t pos;
        while((pos=path.find(".."))!=string::npos) {
            path.erase(pos, 1);
        }

        filename+=path;
        ifstream ifs;
        //A simple platform-independent file-or-directory check do not exist, but this works in most of the cases:
        if(filename.find('.')==string::npos) {
            if(filename[filename.length()-1]!='/')
                filename+='/';
            filename+="index.html";
        }
        ifs.open(filename, ifstream::in);

        if(ifs) {
            ifs.seekg(0, ios::end);
            size_t length=ifs.tellg();

            ifs.seekg(0, ios::beg);

            //The file-content is copied to the response-stream. Should not be used for very large files.
            response << "HTTP/1.1 200 OK\r\nContent-Length: " << length << "\r\n\r\n" << ifs.rdbuf();

            ifs.close();
        }
        else {
            string content="Could not open file "+filename;
            response << "HTTP/1.1 400 Bad Request\r\nContent-Length: " << content.length() << "\r\n\r\n" << content;
        }
    };

    thread server_thread([&server](){
        //Start server
        server.start();
    });

    //Wait for server to start so that the client can connect
    this_thread::sleep_for(chrono::seconds(1));

    //Client examples
    //Second Client() parameter set to false: no certificate verification
    Client<HTTPS> client("localhost:8080", false);
    auto r1=client.request("GET", "/match/123");
    cout << r1->content.rdbuf() << endl;

    string json="{\"firstName\": \"John\",\"lastName\": \"Smith\",\"age\": 25}";
    stringstream ss(json);
    auto r2=client.request("POST", "/string", ss);
    cout << r2->content.rdbuf() << endl;

    ss.str(json);
    auto r3=client.request("POST", "/json", ss);
    cout << r3->content.rdbuf() << endl;

    server_thread.join();

    return 0;
}
<|endoftext|>


<commit_before>// Module:  Log4CPLUS
// File:    loglog.cxx
// Created: 6/2001
// Author:  Tad E. Smith
//
//
// Copyright (C) Tad E. Smith  All rights reserved.
//
// This software is published under the terms of the Apache Software
// License version 1.1, a copy of which has been included with this
// distribution in the LICENSE.APL file.
//
// $Log: not supported by cvs2svn $
// Revision 1.4  2003/04/12 13:51:08  tcsmith
// No longer dynamically allocate the object in the "singleton" method.
//
// Revision 1.3  2003/04/03 01:02:02  tcsmith
// Standardized the formatting.
//

#include <log4cplus/streams.h>
#include <log4cplus/helpers/loglog.h>

using namespace std;
using namespace log4cplus::helpers;

///////////////////////////////////////////////////////////////////////////////
// File LOCAL definitions
///////////////////////////////////////////////////////////////////////////////

namespace {
    class _static_LogLog_initializer {
    public:
        _static_LogLog_initializer() { log4cplus::helpers::getLogLog(); }
    } initializer;
}

///////////////////////////////////////////////////////////////////////////////
// public methods
///////////////////////////////////////////////////////////////////////////////

LogLog&
log4cplus::helpers::getLogLog()
{
    static LogLog singleton;
    return singleton;
}

///////////////////////////////////////////////////////////////////////////////
// log4cplus::helpers::LogLog ctor and dtor
///////////////////////////////////////////////////////////////////////////////

LogLog::LogLog()
 : mutex(LOG4CPLUS_MUTEX_CREATE),
   debugEnabled(false),
   quietMode(false),
   PREFIX( LOG4CPLUS_TEXT("log4cplus: ") ),
   WARN_PREFIX( LOG4CPLUS_TEXT("log4cplus:WARN ") ),
   ERR_PREFIX( LOG4CPLUS_TEXT("log4cplus:ERROR ") )
{
}

LogLog::~LogLog()
{
    LOG4CPLUS_MUTEX_FREE( mutex );
}

///////////////////////////////////////////////////////////////////////////////
// log4cplus::helpers::LogLog public methods
///////////////////////////////////////////////////////////////////////////////

void
LogLog::setInternalDebugging(bool enabled)
{
    debugEnabled = enabled;
}

void
LogLog::setQuietMode(bool quietModeVal)
{
    quietMode = quietModeVal;
}

void
LogLog::debug(const log4cplus::tstring& msg)
{
    LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( mutex )
        if(debugEnabled && !quietMode) {
             tcout << PREFIX << msg << endl;
        }
    LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX
}

void
LogLog::warn(const log4cplus::tstring& msg)
{
    LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( mutex )
        if(quietMode) return;

        tcerr << WARN_PREFIX << msg << endl;
    LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX
}

void
LogLog::error(const log4cplus::tstring& msg)
{
    LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( mutex )
        if(quietMode) return;

        tcerr << ERR_PREFIX << msg << endl;
    LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX
}

<commit_msg>Removed the static initializer class.<commit_after>// Module:  Log4CPLUS
// File:    loglog.cxx
// Created: 6/2001
// Author:  Tad E. Smith
//
//
// Copyright (C) Tad E. Smith  All rights reserved.
//
// This software is published under the terms of the Apache Software
// License version 1.1, a copy of which has been included with this
// distribution in the LICENSE.APL file.
//
// $Log: not supported by cvs2svn $
// Revision 1.5  2003/04/18 21:15:17  tcsmith
// Converted from std::string to log4cplus::tstring.
//
// Revision 1.4  2003/04/12 13:51:08  tcsmith
// No longer dynamically allocate the object in the "singleton" method.
//
// Revision 1.3  2003/04/03 01:02:02  tcsmith
// Standardized the formatting.
//

#include <log4cplus/streams.h>
#include <log4cplus/helpers/loglog.h>

using namespace std;
using namespace log4cplus::helpers;

///////////////////////////////////////////////////////////////////////////////
// public methods
///////////////////////////////////////////////////////////////////////////////

LogLog&
log4cplus::helpers::getLogLog()
{
    static LogLog singleton;
    return singleton;
}

///////////////////////////////////////////////////////////////////////////////
// log4cplus::helpers::LogLog ctor and dtor
///////////////////////////////////////////////////////////////////////////////

LogLog::LogLog()
 : mutex(LOG4CPLUS_MUTEX_CREATE),
   debugEnabled(false),
   quietMode(false),
   PREFIX( LOG4CPLUS_TEXT("log4cplus: ") ),
   WARN_PREFIX( LOG4CPLUS_TEXT("log4cplus:WARN ") ),
   ERR_PREFIX( LOG4CPLUS_TEXT("log4cplus:ERROR ") )
{
}

LogLog::~LogLog()
{
    LOG4CPLUS_MUTEX_FREE( mutex );
}

///////////////////////////////////////////////////////////////////////////////
// log4cplus::helpers::LogLog public methods
///////////////////////////////////////////////////////////////////////////////

void
LogLog::setInternalDebugging(bool enabled)
{
    debugEnabled = enabled;
}

void
LogLog::setQuietMode(bool quietModeVal)
{
    quietMode = quietModeVal;
}

void
LogLog::debug(const log4cplus::tstring& msg)
{
    LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( mutex )
        if(debugEnabled && !quietMode) {
             tcout << PREFIX << msg << endl;
        }
    LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX
}

void
LogLog::warn(const log4cplus::tstring& msg)
{
    LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( mutex )
        if(quietMode) return;

        tcerr << WARN_PREFIX << msg << endl;
    LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX
}

void
LogLog::error(const log4cplus::tstring& msg)
{
    LOG4CPLUS_BEGIN_SYNCHRONIZE_ON_MUTEX( mutex )
        if(quietMode) return;

        tcerr << ERR_PREFIX << msg << endl;
    LOG4CPLUS_END_SYNCHRONIZE_ON_MUTEX
}

<|endoftext|>


<commit_before>
/*
 * Copyright (C) 2010, Directed Edge, Inc. | Licensed under the MPL and LGPL
 */

#include <QActiveResource.h>
#include <QDateTime>
#include <ruby.h>

typedef VALUE(*ARGS)(...);
typedef int(*ITERATOR)(...);

static VALUE rb_mQAR;
static VALUE rb_cQARHash;
static VALUE rb_cQARParamList;
static VALUE rb_cQARResource;

/*
 * Symbols
 */

static const ID _all = rb_intern("all");
static const ID _allocate = rb_intern("allocate");
static const ID _at = rb_intern("at");
static const ID _collection_name = rb_intern("collection_name");
static const ID _element_name = rb_intern("element_name");
static const ID _first = rb_intern("first");
static const ID _follow_redirects = rb_intern("follow_redirects");
static const ID _new = rb_intern("new");
static const ID _one = rb_intern("one");
static const ID _params = rb_intern("params");
static const ID _site = rb_intern("site");
static const ID _to_s = rb_intern("to_s");
static const ID _last = rb_intern("last");

/*
 * Instance variable symbols
 */

static const ID __attributes = rb_intern("@attributes");
static const ID __prefix_options = rb_intern("@prefix_options");
static const ID __qar_resource = rb_intern("@qar_resource");

static QString to_s(VALUE value)
{
    VALUE s = rb_funcall(value, _to_s, 0);
    return QString::fromUtf8(StringValuePtr(s));
}

static VALUE to_value(const QVariant &v)
{
    switch(v.type())
    {
    case QVariant::Hash:
    {
        VALUE value = rb_funcall(rb_cQARHash, _new, 0);
        QHash<QString, QVariant> hash = v.toHash();

        for(QHash<QString, QVariant>::ConstIterator it = hash.begin(); it != hash.end(); ++it)
        {
            rb_hash_aset(value, rb_str_new2(it.key().toUtf8()), to_value(it.value()));
        }

        return value;
    }
    case QVariant::List:
    {
        VALUE value = rb_ary_new();

        foreach(QVariant element, v.toList())
        {
            rb_ary_push(value, to_value(element));
        }

        return value;
    }
    case QVariant::Invalid:
        return Qnil;
    case QVariant::Bool:
        return v.toBool() ? Qtrue : Qfalse;
    case QVariant::Int:
        return rb_int_new(v.toInt());
    case QVariant::Double:
        return rb_float_new(v.toDouble());
    case QVariant::DateTime:
    {
        return rb_funcall(rb_cTime, _at, 1, rb_int_new(v.toDateTime().toTime_t()));
    }
    default:
        return rb_str_new2(v.toString().toUtf8());
    }
}

static VALUE to_record(VALUE klass, const QVariant &v)
{
    VALUE record = rb_funcall(klass, _allocate, 0);
    rb_ivar_set(record, __attributes, to_value(v));
    rb_ivar_set(record, __prefix_options, rb_hash_new());
    return record;
}

/*
 * Resource
 */

static void resource_mark(QActiveResource::Resource *) {}
static void resource_free(QActiveResource::Resource *resource)
{
    delete resource;
}

static VALUE resource_allocate(VALUE klass)
{
    QActiveResource::Resource *resource = new QActiveResource::Resource;
    return Data_Wrap_Struct(klass, resource_mark, resource_free, resource);
}

/*
 * ParamList
 */

static VALUE param_list_mark(QActiveResource::ParamList *) {}
static VALUE param_list_free(QActiveResource::ParamList *params)
{
    delete params;
}

static VALUE param_list_allocate(VALUE klass)
{
    QActiveResource::ParamList *params = new QActiveResource::ParamList();
    return Data_Wrap_Struct(klass, param_list_mark, param_list_free, params);
}

static int params_hash_iterator(VALUE key, VALUE value, VALUE params)
{
    QActiveResource::ParamList *params_pointer;
    Data_Get_Struct(params, QActiveResource::ParamList, params_pointer);
    params_pointer->append(QActiveResource::Param(to_s(key), to_s(value)));
}

/*
 * QAR
 */

static VALUE qar_find(int argc, VALUE *argv, VALUE self)
{
    VALUE member = rb_ivar_get(self, __qar_resource);
    QActiveResource::Resource *resource = 0;

    if(member == Qnil)
    {
        member = rb_funcall(rb_cQARResource, _new, 0);
        rb_ivar_set(self, __qar_resource, member);
        Data_Get_Struct(member, QActiveResource::Resource, resource);
        resource->setBase(to_s(rb_funcall(self, _site, 0)));
    }
    else
    {
        Data_Get_Struct(member, QActiveResource::Resource, resource);
    }

    VALUE params = param_list_allocate(rb_cData);

    if(argc >= 2 && TYPE(argv[1]) == T_HASH)
    {
        VALUE params_hash = rb_hash_aref(argv[1], ID2SYM(_params));

        if(params_hash != Qnil)
        {
            rb_hash_foreach(params_hash, (ITERATOR) params_hash_iterator, params);
        }

        VALUE follow_redirects = rb_hash_aref(argv[1], ID2SYM(_follow_redirects));
        resource->setFollowRedirects(follow_redirects == Qtrue);
    }

    QActiveResource::ParamList *params_pointer;
    Data_Get_Struct(params, QActiveResource::ParamList, params_pointer);

    QString from;
    resource->setResource(to_s(rb_funcall(self, _collection_name, 0)));

    if(argc >= 1)
    {
        ID current = SYM2ID(argv[0]);

        if(current == _one)
        {
            resource->setResource(to_s(rb_funcall(self, _element_name, 0)));
            return to_record(self, resource->find(QActiveResource::FindOne, from, *params_pointer));
        }
        else if(current == _first)
        {
            return to_record(self, resource->find(QActiveResource::FindFirst, from, *params_pointer));
        }
        else if(current == _last)
        {
            return to_record(self, resource->find(QActiveResource::FindLast, from, *params_pointer));
        }
        else if(current != _all)
        {
            resource->setResource(to_s(rb_funcall(self, _element_name, 0)));
            return to_record(self, resource->find(to_s(argv[0])));
        }
    }

    QActiveResource::RecordList records =
        resource->find(QActiveResource::FindAll, from, *params_pointer);

    VALUE array = rb_ary_new2(records.length());

    for(int i = 0; i < records.length(); i++)
    {
        rb_ary_store(array, i, to_record(self, records[i]));
    }

    return array;
}

extern "C"
{
    void Init_QAR(void)
    {
        rb_mQAR = rb_define_module("QAR");

        rb_cQARHash = rb_define_class_under(rb_mQAR, "Hash", rb_cHash);

        rb_cQARParamList = rb_define_class_under(rb_mQAR, "ParamList", rb_cObject);
        rb_define_alloc_func(rb_cQARParamList, param_list_allocate);

        rb_cQARResource = rb_define_class_under(rb_mQAR, "Resource", rb_cObject);
        rb_define_alloc_func(rb_cQARResource, resource_allocate);

        rb_define_method(rb_mQAR, "find", (ARGS) qar_find, -1);
    }
}
<commit_msg>Not using our own hash anymore<commit_after>
/*
 * Copyright (C) 2010, Directed Edge, Inc. | Licensed under the MPL and LGPL
 */

#include <QActiveResource.h>
#include <QDateTime>
#include <ruby.h>

typedef VALUE(*ARGS)(...);
typedef int(*ITERATOR)(...);

static VALUE rb_mQAR;
static VALUE rb_cQARParamList;
static VALUE rb_cQARResource;

/*
 * Symbols
 */

static const ID _all = rb_intern("all");
static const ID _allocate = rb_intern("allocate");
static const ID _at = rb_intern("at");
static const ID _collection_name = rb_intern("collection_name");
static const ID _element_name = rb_intern("element_name");
static const ID _first = rb_intern("first");
static const ID _follow_redirects = rb_intern("follow_redirects");
static const ID _new = rb_intern("new");
static const ID _one = rb_intern("one");
static const ID _params = rb_intern("params");
static const ID _site = rb_intern("site");
static const ID _to_s = rb_intern("to_s");
static const ID _last = rb_intern("last");

/*
 * Instance variable symbols
 */

static const ID __attributes = rb_intern("@attributes");
static const ID __prefix_options = rb_intern("@prefix_options");
static const ID __qar_resource = rb_intern("@qar_resource");

static QString to_s(VALUE value)
{
    VALUE s = rb_funcall(value, _to_s, 0);
    return QString::fromUtf8(StringValuePtr(s));
}

static VALUE to_value(const QVariant &v)
{
    switch(v.type())
    {
    case QVariant::Hash:
    {
        VALUE value = rb_hash_new();
        QHash<QString, QVariant> hash = v.toHash();

        for(QHash<QString, QVariant>::ConstIterator it = hash.begin(); it != hash.end(); ++it)
        {
            rb_hash_aset(value, rb_str_new2(it.key().toUtf8()), to_value(it.value()));
        }

        return value;
    }
    case QVariant::List:
    {
        VALUE value = rb_ary_new();

        foreach(QVariant element, v.toList())
        {
            rb_ary_push(value, to_value(element));
        }

        return value;
    }
    case QVariant::Invalid:
        return Qnil;
    case QVariant::Bool:
        return v.toBool() ? Qtrue : Qfalse;
    case QVariant::Int:
        return rb_int_new(v.toInt());
    case QVariant::Double:
        return rb_float_new(v.toDouble());
    case QVariant::DateTime:
    {
        return rb_funcall(rb_cTime, _at, 1, rb_int_new(v.toDateTime().toTime_t()));
    }
    default:
        return rb_str_new2(v.toString().toUtf8());
    }
}

static VALUE to_record(VALUE klass, const QVariant &v)
{
    VALUE record = rb_funcall(klass, _allocate, 0);
    rb_ivar_set(record, __attributes, to_value(v));
    rb_ivar_set(record, __prefix_options, rb_hash_new());
    return record;
}

/*
 * Resource
 */

static void resource_mark(QActiveResource::Resource *) {}
static void resource_free(QActiveResource::Resource *resource)
{
    delete resource;
}

static VALUE resource_allocate(VALUE klass)
{
    QActiveResource::Resource *resource = new QActiveResource::Resource;
    return Data_Wrap_Struct(klass, resource_mark, resource_free, resource);
}

/*
 * ParamList
 */

static VALUE param_list_mark(QActiveResource::ParamList *) {}
static VALUE param_list_free(QActiveResource::ParamList *params)
{
    delete params;
}

static VALUE param_list_allocate(VALUE klass)
{
    QActiveResource::ParamList *params = new QActiveResource::ParamList();
    return Data_Wrap_Struct(klass, param_list_mark, param_list_free, params);
}

static int params_hash_iterator(VALUE key, VALUE value, VALUE params)
{
    QActiveResource::ParamList *params_pointer;
    Data_Get_Struct(params, QActiveResource::ParamList, params_pointer);
    params_pointer->append(QActiveResource::Param(to_s(key), to_s(value)));
}

/*
 * QAR
 */

static VALUE qar_find(int argc, VALUE *argv, VALUE self)
{
    VALUE member = rb_ivar_get(self, __qar_resource);
    QActiveResource::Resource *resource = 0;

    if(member == Qnil)
    {
        member = rb_funcall(rb_cQARResource, _new, 0);
        rb_ivar_set(self, __qar_resource, member);
        Data_Get_Struct(member, QActiveResource::Resource, resource);
        resource->setBase(to_s(rb_funcall(self, _site, 0)));
    }
    else
    {
        Data_Get_Struct(member, QActiveResource::Resource, resource);
    }

    VALUE params = param_list_allocate(rb_cData);

    if(argc >= 2 && TYPE(argv[1]) == T_HASH)
    {
        VALUE params_hash = rb_hash_aref(argv[1], ID2SYM(_params));

        if(params_hash != Qnil)
        {
            rb_hash_foreach(params_hash, (ITERATOR) params_hash_iterator, params);
        }

        VALUE follow_redirects = rb_hash_aref(argv[1], ID2SYM(_follow_redirects));
        resource->setFollowRedirects(follow_redirects == Qtrue);
    }

    QActiveResource::ParamList *params_pointer;
    Data_Get_Struct(params, QActiveResource::ParamList, params_pointer);

    QString from;
    resource->setResource(to_s(rb_funcall(self, _collection_name, 0)));

    if(argc >= 1)
    {
        ID current = SYM2ID(argv[0]);

        if(current == _one)
        {
            resource->setResource(to_s(rb_funcall(self, _element_name, 0)));
            return to_record(self, resource->find(QActiveResource::FindOne, from, *params_pointer));
        }
        else if(current == _first)
        {
            return to_record(self, resource->find(QActiveResource::FindFirst, from, *params_pointer));
        }
        else if(current == _last)
        {
            return to_record(self, resource->find(QActiveResource::FindLast, from, *params_pointer));
        }
        else if(current != _all)
        {
            resource->setResource(to_s(rb_funcall(self, _element_name, 0)));
            return to_record(self, resource->find(to_s(argv[0])));
        }
    }

    QActiveResource::RecordList records =
        resource->find(QActiveResource::FindAll, from, *params_pointer);

    VALUE array = rb_ary_new2(records.length());

    for(int i = 0; i < records.length(); i++)
    {
        rb_ary_store(array, i, to_record(self, records[i]));
    }

    return array;
}

extern "C"
{
    void Init_QAR(void)
    {
        rb_mQAR = rb_define_module("QAR");

        rb_cQARParamList = rb_define_class_under(rb_mQAR, "ParamList", rb_cObject);
        rb_define_alloc_func(rb_cQARParamList, param_list_allocate);

        rb_cQARResource = rb_define_class_under(rb_mQAR, "Resource", rb_cObject);
        rb_define_alloc_func(rb_cQARResource, resource_allocate);

        rb_define_method(rb_mQAR, "find", (ARGS) qar_find, -1);
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
//
#include "grpc_transcoding/path_matcher_utility.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"

using google::api::HttpRule;
using google::grpc::transcoding::PathMatcherBuilder;
using google::grpc::transcoding::PathMatcherUtility;

using testing::_;
using testing::Eq;
using testing::Return;

class TestMethod {};

namespace google {
namespace grpc {
namespace transcoding {
template <>
class PathMatcherBuilder<const TestMethod*> {
 public:
  MOCK_METHOD5(Register,
               bool(const std::string&, const std::string&, const std::string&,
                    const std::unordered_set<std::string>&, const TestMethod*));
};
}
}
}

class PathMatcherUtilityTest : public ::testing::Test {
 public:
  PathMatcherUtilityTest() : method1_(), method2_() {}

  PathMatcherBuilder<const TestMethod*> pmb;
  const TestMethod method1_;
  const TestMethod method2_;
};

TEST_F(PathMatcherUtilityTest, NeverRegister) {
  HttpRule http_rule;
  EXPECT_CALL(pmb, Register(_, _, _, _, _)).Times(0);
  ASSERT_TRUE(
      PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, &method1_));
}

TEST_F(PathMatcherUtilityTest, RegisterGet) {
  HttpRule http_rule;
  http_rule.set_get("/path");
  http_rule.set_body("body");
  EXPECT_CALL(pmb, Register(Eq("GET"), Eq("/path"), Eq("body"),
                            Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  ASSERT_TRUE(
      PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, &method1_));
  EXPECT_CALL(pmb, Register(Eq("GET"), Eq("/path"), Eq("body"),
                            Eq(std::unordered_set<std::string>{"key"}), Eq(&method2_)))
      .WillOnce(Return(false));
  ASSERT_FALSE(PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, {"key"},
                                                      &method2_));
}

TEST_F(PathMatcherUtilityTest, RegisterPut) {
  HttpRule http_rule;
  http_rule.set_put("/path");
  http_rule.set_body("body");
  EXPECT_CALL(pmb, Register(Eq("PUT"), Eq("/path"), Eq("body"),
                            Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  ASSERT_TRUE(
      PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, &method1_));
  EXPECT_CALL(pmb, Register(Eq("PUT"), Eq("/path"), Eq("body"),
                            Eq(std::unordered_set<std::string>{"key"}), Eq(&method2_)))
      .WillOnce(Return(false));
  ASSERT_FALSE(PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, {"key"},
                                                      &method2_));
}

TEST_F(PathMatcherUtilityTest, RegisterPost) {
  HttpRule http_rule;
  http_rule.set_post("/path");
  http_rule.set_body("body");
  EXPECT_CALL(pmb, Register(Eq("POST"), Eq("/path"), Eq("body"),
                            Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  ASSERT_TRUE(
      PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, &method1_));
  EXPECT_CALL(pmb, Register(Eq("POST"), Eq("/path"), Eq("body"),
                            Eq(std::unordered_set<std::string>{"key"}), Eq(&method2_)))
      .WillOnce(Return(false));
  ASSERT_FALSE(PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, {"key"},
                                                      &method2_));
}

TEST_F(PathMatcherUtilityTest, RegisterDelete) {
  HttpRule http_rule;
  http_rule.set_delete_("/path");
  http_rule.set_body("body");
  EXPECT_CALL(pmb, Register(Eq("DELETE"), Eq("/path"), Eq("body"),
                            Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  ASSERT_TRUE(
      PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, &method1_));
  EXPECT_CALL(pmb, Register(Eq("DELETE"), Eq("/path"), Eq("body"),
                            Eq(std::unordered_set<std::string>{"key"}), Eq(&method2_)))
      .WillOnce(Return(false));
  ASSERT_FALSE(PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, {"key"},
                                                      &method2_));
}

TEST_F(PathMatcherUtilityTest, RegisterPatch) {
  HttpRule http_rule;
  http_rule.set_patch("/path");
  http_rule.set_body("body");
  EXPECT_CALL(pmb, Register(Eq("PATCH"), Eq("/path"), Eq("body"),
                            Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  ASSERT_TRUE(
      PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, &method1_));
  EXPECT_CALL(pmb, Register(Eq("PATCH"), Eq("/path"), Eq("body"),
                            Eq(std::unordered_set<std::string>{"key"}), Eq(&method2_)))
      .WillOnce(Return(false));
  ASSERT_FALSE(PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, {"key"},
                                                      &method2_));
}

TEST_F(PathMatcherUtilityTest, RegisterCustom) {
  HttpRule http_rule;
  http_rule.mutable_custom()->set_kind("OPTIONS");
  http_rule.mutable_custom()->set_path("/custom_path");
  http_rule.set_body("body");
  EXPECT_CALL(pmb, Register(Eq("OPTIONS"), Eq("/custom_path"), Eq("body"),
                            Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  ASSERT_TRUE(
      PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, &method1_));
  EXPECT_CALL(pmb, Register(Eq("OPTIONS"), Eq("/custom_path"), Eq("body"),
                            Eq(std::unordered_set<std::string>{"key"}), Eq(&method2_)))
      .WillOnce(Return(false));
  ASSERT_FALSE(PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, {"key"},
                                                      &method2_));
}

TEST_F(PathMatcherUtilityTest, RegisterAdditionalBindings) {
  HttpRule http_rule;
  http_rule.set_get("/path");
  http_rule.set_body("body");

  HttpRule& custom_http_rule1 = *http_rule.add_additional_bindings();
  custom_http_rule1.mutable_custom()->set_kind("OPTIONS");
  custom_http_rule1.mutable_custom()->set_path("/custom_path");
  custom_http_rule1.set_body("body1");

  HttpRule& custom_http_rule2 = *http_rule.add_additional_bindings();
  custom_http_rule2.mutable_custom()->set_kind("HEAD");
  custom_http_rule2.mutable_custom()->set_path("/path");

  HttpRule& custom_http_rule3 = *http_rule.add_additional_bindings();
  custom_http_rule3.set_put("/put_path");

  EXPECT_CALL(pmb, Register(Eq("GET"), Eq("/path"), Eq("body"),
                            Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  EXPECT_CALL(pmb, Register(Eq("OPTIONS"), Eq("/custom_path"), Eq("body1"),
                            Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  EXPECT_CALL(pmb, Register(Eq("HEAD"), Eq("/path"), Eq(""),
                            Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  EXPECT_CALL(pmb, Register(Eq("PUT"), Eq("/put_path"), Eq(""),
                            Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  ASSERT_TRUE(
      PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, &method1_));

  EXPECT_CALL(pmb, Register(Eq("GET"), Eq("/path"), Eq("body"),
                            Eq(std::unordered_set<std::string>{"key"}), Eq(&method2_)))
      .WillOnce(Return(true));
  EXPECT_CALL(pmb, Register(Eq("OPTIONS"), Eq("/custom_path"), Eq("body1"),
                            Eq(std::unordered_set<std::string>{"key"}), Eq(&method2_)))
      .WillOnce(Return(false));
  ASSERT_FALSE(PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, {"key"},
                                                      &method2_));
}
<commit_msg>Run clang-format<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
//
#include "grpc_transcoding/path_matcher_utility.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"

using google::api::HttpRule;
using google::grpc::transcoding::PathMatcherBuilder;
using google::grpc::transcoding::PathMatcherUtility;

using testing::_;
using testing::Eq;
using testing::Return;

class TestMethod {};

namespace google {
namespace grpc {
namespace transcoding {
template <>
class PathMatcherBuilder<const TestMethod*> {
 public:
  MOCK_METHOD5(Register,
               bool(const std::string&, const std::string&, const std::string&,
                    const std::unordered_set<std::string>&, const TestMethod*));
};
}  // namespace transcoding
}  // namespace grpc
}  // namespace google

class PathMatcherUtilityTest : public ::testing::Test {
 public:
  PathMatcherUtilityTest() : method1_(), method2_() {}

  PathMatcherBuilder<const TestMethod*> pmb;
  const TestMethod method1_;
  const TestMethod method2_;
};

TEST_F(PathMatcherUtilityTest, NeverRegister) {
  HttpRule http_rule;
  EXPECT_CALL(pmb, Register(_, _, _, _, _)).Times(0);
  ASSERT_TRUE(
      PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, &method1_));
}

TEST_F(PathMatcherUtilityTest, RegisterGet) {
  HttpRule http_rule;
  http_rule.set_get("/path");
  http_rule.set_body("body");
  EXPECT_CALL(pmb,
              Register(Eq("GET"), Eq("/path"), Eq("body"),
                       Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  ASSERT_TRUE(
      PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, &method1_));
  EXPECT_CALL(
      pmb, Register(Eq("GET"), Eq("/path"), Eq("body"),
                    Eq(std::unordered_set<std::string>{"key"}), Eq(&method2_)))
      .WillOnce(Return(false));
  ASSERT_FALSE(PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, {"key"},
                                                      &method2_));
}

TEST_F(PathMatcherUtilityTest, RegisterPut) {
  HttpRule http_rule;
  http_rule.set_put("/path");
  http_rule.set_body("body");
  EXPECT_CALL(pmb,
              Register(Eq("PUT"), Eq("/path"), Eq("body"),
                       Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  ASSERT_TRUE(
      PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, &method1_));
  EXPECT_CALL(
      pmb, Register(Eq("PUT"), Eq("/path"), Eq("body"),
                    Eq(std::unordered_set<std::string>{"key"}), Eq(&method2_)))
      .WillOnce(Return(false));
  ASSERT_FALSE(PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, {"key"},
                                                      &method2_));
}

TEST_F(PathMatcherUtilityTest, RegisterPost) {
  HttpRule http_rule;
  http_rule.set_post("/path");
  http_rule.set_body("body");
  EXPECT_CALL(pmb,
              Register(Eq("POST"), Eq("/path"), Eq("body"),
                       Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  ASSERT_TRUE(
      PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, &method1_));
  EXPECT_CALL(
      pmb, Register(Eq("POST"), Eq("/path"), Eq("body"),
                    Eq(std::unordered_set<std::string>{"key"}), Eq(&method2_)))
      .WillOnce(Return(false));
  ASSERT_FALSE(PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, {"key"},
                                                      &method2_));
}

TEST_F(PathMatcherUtilityTest, RegisterDelete) {
  HttpRule http_rule;
  http_rule.set_delete_("/path");
  http_rule.set_body("body");
  EXPECT_CALL(pmb,
              Register(Eq("DELETE"), Eq("/path"), Eq("body"),
                       Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  ASSERT_TRUE(
      PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, &method1_));
  EXPECT_CALL(
      pmb, Register(Eq("DELETE"), Eq("/path"), Eq("body"),
                    Eq(std::unordered_set<std::string>{"key"}), Eq(&method2_)))
      .WillOnce(Return(false));
  ASSERT_FALSE(PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, {"key"},
                                                      &method2_));
}

TEST_F(PathMatcherUtilityTest, RegisterPatch) {
  HttpRule http_rule;
  http_rule.set_patch("/path");
  http_rule.set_body("body");
  EXPECT_CALL(pmb,
              Register(Eq("PATCH"), Eq("/path"), Eq("body"),
                       Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  ASSERT_TRUE(
      PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, &method1_));
  EXPECT_CALL(
      pmb, Register(Eq("PATCH"), Eq("/path"), Eq("body"),
                    Eq(std::unordered_set<std::string>{"key"}), Eq(&method2_)))
      .WillOnce(Return(false));
  ASSERT_FALSE(PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, {"key"},
                                                      &method2_));
}

TEST_F(PathMatcherUtilityTest, RegisterCustom) {
  HttpRule http_rule;
  http_rule.mutable_custom()->set_kind("OPTIONS");
  http_rule.mutable_custom()->set_path("/custom_path");
  http_rule.set_body("body");
  EXPECT_CALL(pmb,
              Register(Eq("OPTIONS"), Eq("/custom_path"), Eq("body"),
                       Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  ASSERT_TRUE(
      PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, &method1_));
  EXPECT_CALL(
      pmb, Register(Eq("OPTIONS"), Eq("/custom_path"), Eq("body"),
                    Eq(std::unordered_set<std::string>{"key"}), Eq(&method2_)))
      .WillOnce(Return(false));
  ASSERT_FALSE(PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, {"key"},
                                                      &method2_));
}

TEST_F(PathMatcherUtilityTest, RegisterAdditionalBindings) {
  HttpRule http_rule;
  http_rule.set_get("/path");
  http_rule.set_body("body");

  HttpRule& custom_http_rule1 = *http_rule.add_additional_bindings();
  custom_http_rule1.mutable_custom()->set_kind("OPTIONS");
  custom_http_rule1.mutable_custom()->set_path("/custom_path");
  custom_http_rule1.set_body("body1");

  HttpRule& custom_http_rule2 = *http_rule.add_additional_bindings();
  custom_http_rule2.mutable_custom()->set_kind("HEAD");
  custom_http_rule2.mutable_custom()->set_path("/path");

  HttpRule& custom_http_rule3 = *http_rule.add_additional_bindings();
  custom_http_rule3.set_put("/put_path");

  EXPECT_CALL(pmb,
              Register(Eq("GET"), Eq("/path"), Eq("body"),
                       Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  EXPECT_CALL(pmb,
              Register(Eq("OPTIONS"), Eq("/custom_path"), Eq("body1"),
                       Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  EXPECT_CALL(pmb,
              Register(Eq("HEAD"), Eq("/path"), Eq(""),
                       Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  EXPECT_CALL(pmb,
              Register(Eq("PUT"), Eq("/put_path"), Eq(""),
                       Eq(std::unordered_set<std::string>()), Eq(&method1_)))
      .WillOnce(Return(true));
  ASSERT_TRUE(
      PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, &method1_));

  EXPECT_CALL(
      pmb, Register(Eq("GET"), Eq("/path"), Eq("body"),
                    Eq(std::unordered_set<std::string>{"key"}), Eq(&method2_)))
      .WillOnce(Return(true));
  EXPECT_CALL(
      pmb, Register(Eq("OPTIONS"), Eq("/custom_path"), Eq("body1"),
                    Eq(std::unordered_set<std::string>{"key"}), Eq(&method2_)))
      .WillOnce(Return(false));
  ASSERT_FALSE(PathMatcherUtility::RegisterByHttpRule(pmb, http_rule, {"key"},
                                                      &method2_));
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <pthread.h>
#include <memory.h>
#include <iostream>
#include "util/exception.h"

#define LEAN_MIN_STACK_SPACE 128*1024  // 128 Kb

namespace lean {
void throw_get_stack_size_failed() {
    throw exception("failed to retrieve thread stack size");
}

#ifdef LEAN_WINDOWS
size_t get_stack_size(int main) {
    return LEAN_WIN_STACK_SIZE;
}
#elif defined (__APPLE__)
#include <sys/resource.h>
size_t get_stack_size(int main) {
    if (main) {
        // Retrieve stack size of the main thread.
        struct rlimit curr;
        if (getrlimit(RLIMIT_STACK, &curr) != 0) {
            throw_get_stack_size_failed();
        }
        return curr.rlim_max;
    } else {
        // This branch retrieves the default thread size for pthread threads.
        // This is *not* the stack size of the main thread.
        pthread_attr_t attr;
        memset (&attr, 0, sizeof(attr));
        pthread_attr_init(&attr);
        size_t result;
        if (pthread_attr_getstacksize(&attr, &result) != 0) {
            throw_get_stack_size_failed();
        }
        return result;
    }
}
#else
size_t get_stack_size(int ) {
    pthread_attr_t attr;
    memset (&attr, 0, sizeof(attr));
    if (pthread_getattr_np(pthread_self(), &attr) != 0) {
        throw_get_stack_size_failed();
    }
    void * ptr;
    size_t result;
    if (pthread_attr_getstack (&attr, &ptr, &result) != 0) {
        throw_get_stack_size_failed();
    }
    if (pthread_attr_destroy(&attr) != 0) {
        throw_get_stack_size_failed();
    }
    return result;
}
#endif

static thread_local size_t g_stack_size;
static thread_local size_t g_stack_base;

void save_stack_info(bool main) {
    g_stack_size = get_stack_size(main);
    char x;
    g_stack_base = reinterpret_cast<size_t>(&x);
}

size_t get_used_stack_size() {
    char y;
    size_t curr_stack = reinterpret_cast<size_t>(&y);
    return g_stack_base - curr_stack;
}

size_t get_available_stack_size() {
    size_t sz = get_used_stack_size();
    if (sz > g_stack_size)
        return 0;
    else
        return g_stack_size - sz;
}

void check_stack() {
    if (get_used_stack_size() + LEAN_MIN_STACK_SPACE > g_stack_size)
        throw stack_space_exception();
}
}
<commit_msg>fix(util/stackinfo): compilation warning on cygwin/mingw<commit_after>/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <pthread.h>
#include <memory.h>
#include <iostream>
#include "util/exception.h"

#define LEAN_MIN_STACK_SPACE 128*1024  // 128 Kb

namespace lean {
void throw_get_stack_size_failed() {
    throw exception("failed to retrieve thread stack size");
}

#ifdef LEAN_WINDOWS
size_t get_stack_size(int ) {
    return LEAN_WIN_STACK_SIZE;
}
#elif defined (__APPLE__)
#include <sys/resource.h>
size_t get_stack_size(int main) {
    if (main) {
        // Retrieve stack size of the main thread.
        struct rlimit curr;
        if (getrlimit(RLIMIT_STACK, &curr) != 0) {
            throw_get_stack_size_failed();
        }
        return curr.rlim_max;
    } else {
        // This branch retrieves the default thread size for pthread threads.
        // This is *not* the stack size of the main thread.
        pthread_attr_t attr;
        memset (&attr, 0, sizeof(attr));
        pthread_attr_init(&attr);
        size_t result;
        if (pthread_attr_getstacksize(&attr, &result) != 0) {
            throw_get_stack_size_failed();
        }
        return result;
    }
}
#else
size_t get_stack_size(int ) {
    pthread_attr_t attr;
    memset (&attr, 0, sizeof(attr));
    if (pthread_getattr_np(pthread_self(), &attr) != 0) {
        throw_get_stack_size_failed();
    }
    void * ptr;
    size_t result;
    if (pthread_attr_getstack (&attr, &ptr, &result) != 0) {
        throw_get_stack_size_failed();
    }
    if (pthread_attr_destroy(&attr) != 0) {
        throw_get_stack_size_failed();
    }
    return result;
}
#endif

static thread_local size_t g_stack_size;
static thread_local size_t g_stack_base;

void save_stack_info(bool main) {
    g_stack_size = get_stack_size(main);
    char x;
    g_stack_base = reinterpret_cast<size_t>(&x);
}

size_t get_used_stack_size() {
    char y;
    size_t curr_stack = reinterpret_cast<size_t>(&y);
    return g_stack_base - curr_stack;
}

size_t get_available_stack_size() {
    size_t sz = get_used_stack_size();
    if (sz > g_stack_size)
        return 0;
    else
        return g_stack_size - sz;
}

void check_stack() {
    if (get_used_stack_size() + LEAN_MIN_STACK_SPACE > g_stack_size)
        throw stack_space_exception();
}
}
<|endoftext|>