<commit_before>/**
 * Title:        CoreMIDI4J
 * Description:  Core MIDI Device Provider for Java on OS X
 * Copyright:    Copyright (c) 2015-2016
 * Company:      x.factory Librarians
 *
 * @author Derek Cook
 *
 * CoreMIDI4J is an open source Service Provider Interface for supporting external MIDI devices on MAC OS X
 *
 * This file is part of the XCODE project that provides the native implementation of CoreMIDI4J
 *
 * CREDITS - This library uses principles established by OSXMIDI4J, but converted so it operates at the JNI level with no additional libraries required
 *
 */

#include "CoreMidiDeviceProvider.h"

/////////////////////////////////////////////////////////
// Native functions for CoreMidiDeviceProvider
/////////////////////////////////////////////////////////

/*
 * Gets the number of MIDI sources provided by the Core MIDI system
 *
 * Class:     com_coremidi4j_CoreMidiDeviceProvider
 * Method:    getNumberOfSources
 * Signature: ()I
 *
 * @param env		The JNI environment
 * @param obj   The reference to the java object instance that called this native method
 *
 * @return      The number of MIDI sources provided by the Core MIDI system
 *
 */

JNIEXPORT jint JNICALL Java_uk_co_xfactorylibrarians_coremidi4j_CoreMidiDeviceProvider_getNumberOfSources(JNIEnv *env, jobject obj) {

  return (jint) MIDIGetNumberOfSources();

}

/*
 * Gets the number of MIDI destinations provided by the Core MIDI system
 *
 * Class:     com_coremidi4j_CoreMidiDeviceProvider
 * Method:    getNumberOfDestinations
 * Signature: ()I
 *
 * @param env    The JNI environment
 * @param obj    The reference to the java object instance that called this native method
 *
 * @return       The number of MIDI destinations provided by the Core MIDI system
 *
 */

JNIEXPORT jint JNICALL Java_uk_co_xfactorylibrarians_coremidi4j_CoreMidiDeviceProvider_getNumberOfDestinations(JNIEnv *env, jobject obj) {

  return (jint) MIDIGetNumberOfDestinations();

}

/*
 * Gets the specified Core MIDI Source
 *
 * Class:     com_coremidi4j_CoreMidiDeviceProvider
 * Method:    getSource
 * Signature: (I)I
 *
 * @param env            The JNI environment
 * @param obj            The reference to the java object instance that called this native method
 * @param sourceIndex    The index of the MIDI source to get
 *
 * @return               The specified Core MIDI Source
 *
 * @throws               CoreMidiEXception if the source index is not valid
 *
 */

JNIEXPORT jint JNICALL Java_uk_co_xfactorylibrarians_coremidi4j_CoreMidiDeviceProvider_getSource(JNIEnv *env, jobject obj, jint sourceIndex) {

  if ( sourceIndex >= MIDIGetNumberOfSources() ) {

    ThrowException(env,CFSTR("MIDIGetSource"),sourceIndex);

  }

  return MIDIGetSource(sourceIndex);

}

/*
 * Gets the specified Core MIDI Destination
 *
 * Class:     com_coremidi4j_CoreMidiDeviceProvider
 * Method:    getDestination
 * Signature: (I)I
 *
 * @param env                   The JNI environment
 * @param obj                   The reference to the java object instance that called this native method
 * @param destinationIndex      The index of the MIDI destination to get
 *
 * @return                      The specified Core MIDI Destination
 *
 * @throws                      CoreMidiEXception if the destination index is not valid
 *
 */

JNIEXPORT jint JNICALL Java_uk_co_xfactorylibrarians_coremidi4j_CoreMidiDeviceProvider_getDestination(JNIEnv *env, jobject obj, jint destinationIndex) {

  if ( destinationIndex >= MIDIGetNumberOfDestinations() ) {

    ThrowException(env,CFSTR("MIDIGetDestination"), destinationIndex);

  }

  return MIDIGetDestination(destinationIndex);

}

/*
 * Gets the unique ID (UID) of the specified end point
 *
 * Class:     com_coremidi4j_CoreMidiDeviceProvider
 * Method:    getUniqueID
 * Signature: (I)I
 *
 * @param env                   The JNI environment
 * @param obj                   The reference to the java object instance that called this native method
 * @param endPointReference     The end point reference
 *
 * @return                      The unique ID (UID) of the specified end point
 *
 */

JNIEXPORT jint JNICALL Java_uk_co_xfactorylibrarians_coremidi4j_CoreMidiDeviceProvider_getUniqueID(JNIEnv *env, jobject obj, jint endPointReference) {

  SInt32 uid = 0;

  MIDIObjectGetIntegerProperty(endPointReference, kMIDIPropertyUniqueID, &uid);

  return uid;

}

/*
 * Safely obtains a C string pointer from a CFStringRef. We must do it this way, because CFStringGetCStringPtr
 * is free to return NULL for a variety of reasons, including simply not having an efficient way to respond.
 * However, this means that it is the responsibility of the caller to free() the returned pointer when it is
 * no longer needed, unless we returned NULL.
 *
 * @param aString  The CFStringRef
 *
 * @return         A newly allocated C string holding the contents of str, or NULL
 *
 */
char * safeCFStringCopyUTF8String(CFStringRef aString) {
  if (aString == NULL) {
    return NULL;
  }

  CFIndex length = CFStringGetLength(aString);
  CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
  char *buffer = (char *)malloc(maxSize);
  if (CFStringGetCString(aString, buffer, maxSize, kCFStringEncodingUTF8)) {
    return buffer;
  }
  free(buffer); // We failed
  return NULL;
}

/*
 * Safely prints a line describing a retrieved string for debugging purposes.
 * If the string is null, also reports that.
 *
 * @param label    Describes the string being printed
 * @param aString  The CFStringRef to be printed
 *
 */
// Uncomment this if you want to perform the (also commented out) debug printing in the function below.
//void debugPrintCFString(std::string label, CFStringRef aString) {
//  char *cString = safeCFStringCopyUTF8String(aString);
//  std::cout << label << ((cString != NULL)? cString : "<NULL pointer>") << std::endl;
//  free(cString);
//}

/*
 * Creates and gets a MidiDevice.Info object for the specified end point reference
 *
 * Class:     com_coremidi4j_CoreMidiDeviceProvider
 * Method:    getMidiDeviceInfo
 * Signature: (I)Ljavax/sound/midi/MidiDevice/Info;
 *
 * @param env                   The JNI environment
 * @param obj                   The reference to the java object instance that called this native method
 * @param endPointReference     The end point reference
 *
 * @return                      A MidiDevice.Info object for the specified end point reference
 *
 */

JNIEXPORT jobject JNICALL Java_uk_co_xfactorylibrarians_coremidi4j_CoreMidiDeviceProvider_getMidiDeviceInfo(JNIEnv *env, jobject obj, jint endPointReference) {

  MIDIDeviceRef deviceReference       = NULL;
  CFStringRef   deviceName            = NULL;
  CFStringRef   deviceManufacturer    = NULL;
  CFStringRef   deviceModel           = NULL;
  SInt32        deviceOffline         = NULL;
  SInt32        deviceUniqueID        = 0;
  SInt32        deviceDriverVersion   = 0;

  MIDIEntityRef entityReference       = NULL;
  CFStringRef   entityName            = NULL;
  CFStringRef   entityManufacturer    = NULL;
  CFStringRef   entityModel           = NULL;
  SInt32        entityOffline         = NULL;
  SInt32        entityUniqueID        = 0;
  SInt32        entityDriverVersion   = 0;

  // End point reference is in method parameters
  CFStringRef   endpointName          = NULL;
  CFStringRef   endpointManufacturer  = NULL;
  CFStringRef   endpointModel         = NULL;
  SInt32        endpointOffline       = NULL;
  SInt32        endpointUniqueID      = 0;
  SInt32        endpointDriverVersion = 0;

  // Find the Java CoreMIDIDeviceInfo class and its constructor
  jclass javaClass = env->FindClass("uk/co/xfactorylibrarians/coremidi4j/CoreMidiDeviceInfo");
  jmethodID constructor = env->GetMethodID(javaClass, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IILjava/lang/String;IILjava/lang/String;II)V");

  // Get the endpoint properties
  MIDIObjectGetStringProperty (endPointReference, kMIDIPropertyName,          &endpointName);
  MIDIObjectGetStringProperty (endPointReference, kMIDIPropertyModel,         &endpointModel);
  MIDIObjectGetStringProperty (endPointReference, kMIDIPropertyManufacturer,  &endpointManufacturer);
  MIDIObjectGetIntegerProperty(endPointReference, kMIDIPropertyOffline,       &endpointOffline);
  MIDIObjectGetIntegerProperty(endPointReference, kMIDIPropertyUniqueID,      &endpointUniqueID);
  MIDIObjectGetIntegerProperty(endPointReference, kMIDIPropertyDriverVersion, &endpointDriverVersion);

  // Get the entity properties
  MIDIEndpointGetEntity(endPointReference, &entityReference);

  MIDIObjectGetStringProperty (entityReference, kMIDIPropertyName,          &entityName);
  MIDIObjectGetStringProperty (entityReference, kMIDIPropertyModel,         &entityModel);
  MIDIObjectGetStringProperty (entityReference, kMIDIPropertyManufacturer,  &entityManufacturer);
  MIDIObjectGetIntegerProperty(entityReference, kMIDIPropertyOffline,       &entityOffline);
  MIDIObjectGetIntegerProperty(entityReference, kMIDIPropertyUniqueID,      &entityUniqueID);
  MIDIObjectGetIntegerProperty(entityReference, kMIDIPropertyDriverVersion, &entityDriverVersion);

  // Get the device properties
  MIDIEntityGetDevice(entityReference, &deviceReference);

  MIDIObjectGetStringProperty (deviceReference, kMIDIPropertyName,          &deviceName); // Get this again in case our string build fails
  MIDIObjectGetStringProperty (deviceReference, kMIDIPropertyModel,         &deviceModel);
  MIDIObjectGetStringProperty (deviceReference, kMIDIPropertyManufacturer,  &deviceManufacturer);
  MIDIObjectGetIntegerProperty(deviceReference, kMIDIPropertyOffline,       &deviceOffline);
  MIDIObjectGetIntegerProperty(deviceReference, kMIDIPropertyUniqueID,      &deviceUniqueID);
  MIDIObjectGetIntegerProperty(deviceReference, kMIDIPropertyDriverVersion, &deviceDriverVersion);

  long numberOfEntities = MIDIDeviceGetNumberOfEntities(deviceReference);

// Uncomment these lines and debugPrintCFString (above) if you wish to view information as received on the native side during debugging.
//  std::cout << "End Point " << std::endl;
//  std::cout << "  End Point Reference                  " << endPointReference << std::endl;
//  debugPrintCFString("  End Point kMIDIPropertyName          ", endpointName);
//  debugPrintCFString("  End Point kMIDIPropertyModel         ", endpointModel);
//  debugPrintCFString("  End Point kMIDIPropertyManufacturer  ", endpointManufacturer);
//  std::cout << "  End Point kMIDIPropertyOffline       " << endpointOffline << std::endl;
//  std::cout << "  End Point kMIDIPropertyUniqueID      " << endpointUniqueID << std::endl;
//  std::cout << "  End Point kMIDIPropertyDriverVersion " << endpointDriverVersion << std::endl;
//  std::cout << std::endl;
//  std::cout << "  Entity    Reference                  " << entityReference << std::endl;
//  debugPrintCFString("  Entity    kMIDIPropertyName          ", entityName);
//  debugPrintCFString("  Entity    kMIDIPropertyModel         ", entityModel);
//  debugPrintCFString("  Entity    kMIDIPropertyManufacturer  ", entityManufacturer);
//  std::cout << "  Entity    kMIDIPropertyOffline       " << entityOffline << std::endl;
//  std::cout << "  Entity    kMIDIPropertyUniqueID      " << entityUniqueID << std::endl;
//  std::cout << "  Entity    kMIDIPropertyDriverVersion " << entityDriverVersion << std::endl;
//  std::cout << std::endl;
//  std::cout << "  Device    Reference                  " << deviceReference << std::endl;
//  debugPrintCFString("  Device    kMIDIPropertyName          ", deviceName);
//  debugPrintCFString("  Device    kMIDIPropertyModel         ", deviceModel);
//  debugPrintCFString("  Device    kMIDIPropertyManufacturer  ", deviceManufacturer);
//  std::cout << "  Device    kMIDIPropertyOffline       " << deviceOffline << std::endl;
//  std::cout << "  Device    kMIDIPropertyUniqueID      " << deviceUniqueID << std::endl;
//  std::cout << "  Device    kMIDIPropertyDriverVersion " << deviceDriverVersion << std::endl;
//  std::cout << std::endl;
//  std::cout << "  Number of entities                   " << numberOfEntities << std::endl;
//  std::cout << std::endl;

  // Build the Device Info name. Add "CoreMIDI4J - " to the start of our device name if we can
  // And if the device has more than one entity then add the entity name
  CFMutableStringRef buildName = CFStringCreateMutable(NULL, 0);
  CFStringRef deviceInfoName;

  if ( buildName != NULL ) {

    if ( deviceName != NULL ) {

      CFStringAppend(buildName, (deviceName != NULL ) ? deviceName :  CFSTR("<Unknown Device>") );

      if ( numberOfEntities > 1 ) {

        CFStringAppend(buildName, CFSTR(" "));
        CFStringAppend(buildName, (endpointName != NULL ) ? endpointName :  CFSTR("<Unknown Endpoint>") );

      }

    } else {

      CFStringAppend(buildName, (endpointName != NULL ) ? endpointName :  CFSTR("<Unknown Device>") );

    }

    // Overwrite the deviceName with our updated one
    deviceInfoName = CFStringCreateCopy(NULL, buildName);

    // And release the temporary string
    CFRelease(buildName);

  } else {

    // Overwrite the deviceName with our updated one
    deviceInfoName = CFStringCreateCopy(NULL, deviceName);

  }

  char *deviceInfoNamePtr         = safeCFStringCopyUTF8String ( deviceInfoName );
  char *deviceInfoManufacturerPtr = safeCFStringCopyUTF8String ( endpointManufacturer ); // The end point manufacturer name is always present
  char *deviceInfoDescriptionPtr  = safeCFStringCopyUTF8String ( endpointModel );        // The end point model name is always present

  char *deviceNamePtr             = safeCFStringCopyUTF8String ( deviceName );
  char *entityNamePtr             = safeCFStringCopyUTF8String ( entityName );
  char *endPointNamePtr           = safeCFStringCopyUTF8String ( endpointName );

  // TODO - Have seen reference that the device neds to be initialised to get the version. As we are still getting zero, force the string for now
  const char *deviceInfoVersion         = "Unknown Version";

  // Create the Java Object
  jobject info = env->NewObject(javaClass,
                                constructor,
                                env->NewStringUTF(( deviceInfoNamePtr         != NULL ) ? deviceInfoNamePtr         : "<Unknown Device>"),
                                env->NewStringUTF(( deviceInfoManufacturerPtr != NULL ) ? deviceInfoManufacturerPtr : "<Unknown Manufacturer>"),
                                env->NewStringUTF(( deviceInfoDescriptionPtr  != NULL ) ? deviceInfoDescriptionPtr  : "<Unknown Description>"),
                                env->NewStringUTF(deviceInfoVersion),
                                env->NewStringUTF( ( deviceNamePtr != NULL ) ? deviceNamePtr : "<Unknown Device>"),
                                deviceReference,
                                deviceUniqueID,
                                env->NewStringUTF( ( entityNamePtr != NULL) ? entityNamePtr : "<Unknown Entity>"),
                                entityReference,
                                entityUniqueID,
                                env->NewStringUTF( ( endPointNamePtr != NULL ) ? endPointNamePtr : "<Unknown Endpoint>"),
                                endPointReference,
                                endpointUniqueID);

  free(deviceInfoNamePtr);
  free(deviceInfoManufacturerPtr);
  free(deviceInfoDescriptionPtr);
  free(deviceNamePtr);
  free(entityNamePtr);
  free(endPointNamePtr);

  return info;

}
<commit_msg>Fix typo.<commit_after>/**
 * Title:        CoreMIDI4J
 * Description:  Core MIDI Device Provider for Java on OS X
 * Copyright:    Copyright (c) 2015-2016
 * Company:      x.factory Librarians
 *
 * @author Derek Cook
 *
 * CoreMIDI4J is an open source Service Provider Interface for supporting external MIDI devices on MAC OS X
 *
 * This file is part of the XCODE project that provides the native implementation of CoreMIDI4J
 *
 * CREDITS - This library uses principles established by OSXMIDI4J, but converted so it operates at the JNI level with no additional libraries required
 *
 */

#include "CoreMidiDeviceProvider.h"

/////////////////////////////////////////////////////////
// Native functions for CoreMidiDeviceProvider
/////////////////////////////////////////////////////////

/*
 * Gets the number of MIDI sources provided by the Core MIDI system
 *
 * Class:     com_coremidi4j_CoreMidiDeviceProvider
 * Method:    getNumberOfSources
 * Signature: ()I
 *
 * @param env		The JNI environment
 * @param obj   The reference to the java object instance that called this native method
 *
 * @return      The number of MIDI sources provided by the Core MIDI system
 *
 */

JNIEXPORT jint JNICALL Java_uk_co_xfactorylibrarians_coremidi4j_CoreMidiDeviceProvider_getNumberOfSources(JNIEnv *env, jobject obj) {

  return (jint) MIDIGetNumberOfSources();

}

/*
 * Gets the number of MIDI destinations provided by the Core MIDI system
 *
 * Class:     com_coremidi4j_CoreMidiDeviceProvider
 * Method:    getNumberOfDestinations
 * Signature: ()I
 *
 * @param env    The JNI environment
 * @param obj    The reference to the java object instance that called this native method
 *
 * @return       The number of MIDI destinations provided by the Core MIDI system
 *
 */

JNIEXPORT jint JNICALL Java_uk_co_xfactorylibrarians_coremidi4j_CoreMidiDeviceProvider_getNumberOfDestinations(JNIEnv *env, jobject obj) {

  return (jint) MIDIGetNumberOfDestinations();

}

/*
 * Gets the specified Core MIDI Source
 *
 * Class:     com_coremidi4j_CoreMidiDeviceProvider
 * Method:    getSource
 * Signature: (I)I
 *
 * @param env            The JNI environment
 * @param obj            The reference to the java object instance that called this native method
 * @param sourceIndex    The index of the MIDI source to get
 *
 * @return               The specified Core MIDI Source
 *
 * @throws               CoreMidiEXception if the source index is not valid
 *
 */

JNIEXPORT jint JNICALL Java_uk_co_xfactorylibrarians_coremidi4j_CoreMidiDeviceProvider_getSource(JNIEnv *env, jobject obj, jint sourceIndex) {

  if ( sourceIndex >= MIDIGetNumberOfSources() ) {

    ThrowException(env,CFSTR("MIDIGetSource"),sourceIndex);

  }

  return MIDIGetSource(sourceIndex);

}

/*
 * Gets the specified Core MIDI Destination
 *
 * Class:     com_coremidi4j_CoreMidiDeviceProvider
 * Method:    getDestination
 * Signature: (I)I
 *
 * @param env                   The JNI environment
 * @param obj                   The reference to the java object instance that called this native method
 * @param destinationIndex      The index of the MIDI destination to get
 *
 * @return                      The specified Core MIDI Destination
 *
 * @throws                      CoreMidiEXception if the destination index is not valid
 *
 */

JNIEXPORT jint JNICALL Java_uk_co_xfactorylibrarians_coremidi4j_CoreMidiDeviceProvider_getDestination(JNIEnv *env, jobject obj, jint destinationIndex) {

  if ( destinationIndex >= MIDIGetNumberOfDestinations() ) {

    ThrowException(env,CFSTR("MIDIGetDestination"), destinationIndex);

  }

  return MIDIGetDestination(destinationIndex);

}

/*
 * Gets the unique ID (UID) of the specified end point
 *
 * Class:     com_coremidi4j_CoreMidiDeviceProvider
 * Method:    getUniqueID
 * Signature: (I)I
 *
 * @param env                   The JNI environment
 * @param obj                   The reference to the java object instance that called this native method
 * @param endPointReference     The end point reference
 *
 * @return                      The unique ID (UID) of the specified end point
 *
 */

JNIEXPORT jint JNICALL Java_uk_co_xfactorylibrarians_coremidi4j_CoreMidiDeviceProvider_getUniqueID(JNIEnv *env, jobject obj, jint endPointReference) {

  SInt32 uid = 0;

  MIDIObjectGetIntegerProperty(endPointReference, kMIDIPropertyUniqueID, &uid);

  return uid;

}

/*
 * Safely obtains a C string pointer from a CFStringRef. We must do it this way, because CFStringGetCStringPtr
 * is free to return NULL for a variety of reasons, including simply not having an efficient way to respond.
 * However, this means that it is the responsibility of the caller to free() the returned pointer when it is
 * no longer needed, unless we returned NULL.
 *
 * @param aString  The CFStringRef
 *
 * @return         A newly allocated C string holding the contents of aString, or NULL
 *
 */
char * safeCFStringCopyUTF8String(CFStringRef aString) {
  if (aString == NULL) {
    return NULL;
  }

  CFIndex length = CFStringGetLength(aString);
  CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
  char *buffer = (char *)malloc(maxSize);
  if (CFStringGetCString(aString, buffer, maxSize, kCFStringEncodingUTF8)) {
    return buffer;
  }
  free(buffer); // We failed
  return NULL;
}

/*
 * Safely prints a line describing a retrieved string for debugging purposes.
 * If the string is null, also reports that.
 *
 * @param label    Describes the string being printed
 * @param aString  The CFStringRef to be printed
 *
 */
// Uncomment this if you want to perform the (also commented out) debug printing in the function below.
//void debugPrintCFString(std::string label, CFStringRef aString) {
//  char *cString = safeCFStringCopyUTF8String(aString);
//  std::cout << label << ((cString != NULL)? cString : "<NULL pointer>") << std::endl;
//  free(cString);
//}

/*
 * Creates and gets a MidiDevice.Info object for the specified end point reference
 *
 * Class:     com_coremidi4j_CoreMidiDeviceProvider
 * Method:    getMidiDeviceInfo
 * Signature: (I)Ljavax/sound/midi/MidiDevice/Info;
 *
 * @param env                   The JNI environment
 * @param obj                   The reference to the java object instance that called this native method
 * @param endPointReference     The end point reference
 *
 * @return                      A MidiDevice.Info object for the specified end point reference
 *
 */

JNIEXPORT jobject JNICALL Java_uk_co_xfactorylibrarians_coremidi4j_CoreMidiDeviceProvider_getMidiDeviceInfo(JNIEnv *env, jobject obj, jint endPointReference) {

  MIDIDeviceRef deviceReference       = NULL;
  CFStringRef   deviceName            = NULL;
  CFStringRef   deviceManufacturer    = NULL;
  CFStringRef   deviceModel           = NULL;
  SInt32        deviceOffline         = NULL;
  SInt32        deviceUniqueID        = 0;
  SInt32        deviceDriverVersion   = 0;

  MIDIEntityRef entityReference       = NULL;
  CFStringRef   entityName            = NULL;
  CFStringRef   entityManufacturer    = NULL;
  CFStringRef   entityModel           = NULL;
  SInt32        entityOffline         = NULL;
  SInt32        entityUniqueID        = 0;
  SInt32        entityDriverVersion   = 0;

  // End point reference is in method parameters
  CFStringRef   endpointName          = NULL;
  CFStringRef   endpointManufacturer  = NULL;
  CFStringRef   endpointModel         = NULL;
  SInt32        endpointOffline       = NULL;
  SInt32        endpointUniqueID      = 0;
  SInt32        endpointDriverVersion = 0;

  // Find the Java CoreMIDIDeviceInfo class and its constructor
  jclass javaClass = env->FindClass("uk/co/xfactorylibrarians/coremidi4j/CoreMidiDeviceInfo");
  jmethodID constructor = env->GetMethodID(javaClass, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IILjava/lang/String;IILjava/lang/String;II)V");

  // Get the endpoint properties
  MIDIObjectGetStringProperty (endPointReference, kMIDIPropertyName,          &endpointName);
  MIDIObjectGetStringProperty (endPointReference, kMIDIPropertyModel,         &endpointModel);
  MIDIObjectGetStringProperty (endPointReference, kMIDIPropertyManufacturer,  &endpointManufacturer);
  MIDIObjectGetIntegerProperty(endPointReference, kMIDIPropertyOffline,       &endpointOffline);
  MIDIObjectGetIntegerProperty(endPointReference, kMIDIPropertyUniqueID,      &endpointUniqueID);
  MIDIObjectGetIntegerProperty(endPointReference, kMIDIPropertyDriverVersion, &endpointDriverVersion);

  // Get the entity properties
  MIDIEndpointGetEntity(endPointReference, &entityReference);

  MIDIObjectGetStringProperty (entityReference, kMIDIPropertyName,          &entityName);
  MIDIObjectGetStringProperty (entityReference, kMIDIPropertyModel,         &entityModel);
  MIDIObjectGetStringProperty (entityReference, kMIDIPropertyManufacturer,  &entityManufacturer);
  MIDIObjectGetIntegerProperty(entityReference, kMIDIPropertyOffline,       &entityOffline);
  MIDIObjectGetIntegerProperty(entityReference, kMIDIPropertyUniqueID,      &entityUniqueID);
  MIDIObjectGetIntegerProperty(entityReference, kMIDIPropertyDriverVersion, &entityDriverVersion);

  // Get the device properties
  MIDIEntityGetDevice(entityReference, &deviceReference);

  MIDIObjectGetStringProperty (deviceReference, kMIDIPropertyName,          &deviceName); // Get this again in case our string build fails
  MIDIObjectGetStringProperty (deviceReference, kMIDIPropertyModel,         &deviceModel);
  MIDIObjectGetStringProperty (deviceReference, kMIDIPropertyManufacturer,  &deviceManufacturer);
  MIDIObjectGetIntegerProperty(deviceReference, kMIDIPropertyOffline,       &deviceOffline);
  MIDIObjectGetIntegerProperty(deviceReference, kMIDIPropertyUniqueID,      &deviceUniqueID);
  MIDIObjectGetIntegerProperty(deviceReference, kMIDIPropertyDriverVersion, &deviceDriverVersion);

  long numberOfEntities = MIDIDeviceGetNumberOfEntities(deviceReference);

// Uncomment these lines and debugPrintCFString (above) if you wish to view information as received on the native side during debugging.
//  std::cout << "End Point " << std::endl;
//  std::cout << "  End Point Reference                  " << endPointReference << std::endl;
//  debugPrintCFString("  End Point kMIDIPropertyName          ", endpointName);
//  debugPrintCFString("  End Point kMIDIPropertyModel         ", endpointModel);
//  debugPrintCFString("  End Point kMIDIPropertyManufacturer  ", endpointManufacturer);
//  std::cout << "  End Point kMIDIPropertyOffline       " << endpointOffline << std::endl;
//  std::cout << "  End Point kMIDIPropertyUniqueID      " << endpointUniqueID << std::endl;
//  std::cout << "  End Point kMIDIPropertyDriverVersion " << endpointDriverVersion << std::endl;
//  std::cout << std::endl;
//  std::cout << "  Entity    Reference                  " << entityReference << std::endl;
//  debugPrintCFString("  Entity    kMIDIPropertyName          ", entityName);
//  debugPrintCFString("  Entity    kMIDIPropertyModel         ", entityModel);
//  debugPrintCFString("  Entity    kMIDIPropertyManufacturer  ", entityManufacturer);
//  std::cout << "  Entity    kMIDIPropertyOffline       " << entityOffline << std::endl;
//  std::cout << "  Entity    kMIDIPropertyUniqueID      " << entityUniqueID << std::endl;
//  std::cout << "  Entity    kMIDIPropertyDriverVersion " << entityDriverVersion << std::endl;
//  std::cout << std::endl;
//  std::cout << "  Device    Reference                  " << deviceReference << std::endl;
//  debugPrintCFString("  Device    kMIDIPropertyName          ", deviceName);
//  debugPrintCFString("  Device    kMIDIPropertyModel         ", deviceModel);
//  debugPrintCFString("  Device    kMIDIPropertyManufacturer  ", deviceManufacturer);
//  std::cout << "  Device    kMIDIPropertyOffline       " << deviceOffline << std::endl;
//  std::cout << "  Device    kMIDIPropertyUniqueID      " << deviceUniqueID << std::endl;
//  std::cout << "  Device    kMIDIPropertyDriverVersion " << deviceDriverVersion << std::endl;
//  std::cout << std::endl;
//  std::cout << "  Number of entities                   " << numberOfEntities << std::endl;
//  std::cout << std::endl;

  // Build the Device Info name. Add "CoreMIDI4J - " to the start of our device name if we can
  // And if the device has more than one entity then add the entity name
  CFMutableStringRef buildName = CFStringCreateMutable(NULL, 0);
  CFStringRef deviceInfoName;

  if ( buildName != NULL ) {

    if ( deviceName != NULL ) {

      CFStringAppend(buildName, (deviceName != NULL ) ? deviceName :  CFSTR("<Unknown Device>") );

      if ( numberOfEntities > 1 ) {

        CFStringAppend(buildName, CFSTR(" "));
        CFStringAppend(buildName, (endpointName != NULL ) ? endpointName :  CFSTR("<Unknown Endpoint>") );

      }

    } else {

      CFStringAppend(buildName, (endpointName != NULL ) ? endpointName :  CFSTR("<Unknown Device>") );

    }

    // Overwrite the deviceName with our updated one
    deviceInfoName = CFStringCreateCopy(NULL, buildName);

    // And release the temporary string
    CFRelease(buildName);

  } else {

    // Overwrite the deviceName with our updated one
    deviceInfoName = CFStringCreateCopy(NULL, deviceName);

  }

  char *deviceInfoNamePtr         = safeCFStringCopyUTF8String ( deviceInfoName );
  char *deviceInfoManufacturerPtr = safeCFStringCopyUTF8String ( endpointManufacturer ); // The end point manufacturer name is always present
  char *deviceInfoDescriptionPtr  = safeCFStringCopyUTF8String ( endpointModel );        // The end point model name is always present

  char *deviceNamePtr             = safeCFStringCopyUTF8String ( deviceName );
  char *entityNamePtr             = safeCFStringCopyUTF8String ( entityName );
  char *endPointNamePtr           = safeCFStringCopyUTF8String ( endpointName );

  // TODO - Have seen reference that the device neds to be initialised to get the version. As we are still getting zero, force the string for now
  const char *deviceInfoVersion         = "Unknown Version";

  // Create the Java Object
  jobject info = env->NewObject(javaClass,
                                constructor,
                                env->NewStringUTF(( deviceInfoNamePtr         != NULL ) ? deviceInfoNamePtr         : "<Unknown Device>"),
                                env->NewStringUTF(( deviceInfoManufacturerPtr != NULL ) ? deviceInfoManufacturerPtr : "<Unknown Manufacturer>"),
                                env->NewStringUTF(( deviceInfoDescriptionPtr  != NULL ) ? deviceInfoDescriptionPtr  : "<Unknown Description>"),
                                env->NewStringUTF(deviceInfoVersion),
                                env->NewStringUTF( ( deviceNamePtr != NULL ) ? deviceNamePtr : "<Unknown Device>"),
                                deviceReference,
                                deviceUniqueID,
                                env->NewStringUTF( ( entityNamePtr != NULL) ? entityNamePtr : "<Unknown Entity>"),
                                entityReference,
                                entityUniqueID,
                                env->NewStringUTF( ( endPointNamePtr != NULL ) ? endPointNamePtr : "<Unknown Endpoint>"),
                                endPointReference,
                                endpointUniqueID);

  free(deviceInfoNamePtr);
  free(deviceInfoManufacturerPtr);
  free(deviceInfoDescriptionPtr);
  free(deviceNamePtr);
  free(entityNamePtr);
  free(endPointNamePtr);

  return info;

}
<|endoftext|>


<commit_before>/* =======================================================================
   Copyright (c) 2011, Institute for Microelectronics,
                       Institute for Analysis and Scientific Computing,
                       TU Wien.

                            -----------------
                     ViennaGrid - The Vienna Grid Library
                            -----------------

   Authors:      Karl Rupp                           rupp@iue.tuwien.ac.at
                 Josef Weinbub                    weinbub@iue.tuwien.ac.at

   (A list of additional contributors can be found in the PDF manual)

   License:      MIT (X11), see file LICENSE in the base directory
======================================================================= */

#ifdef _MSC_VER      //Visual Studio complains about potentially dangerous things, which are perfectly legal in our context
  #pragma warning( disable : 4355 )     //use of this in member initializer list
  #pragma warning( disable : 4503 )     //truncated name decoration
#endif

#include "viennagrid/forwards.h"
#include "viennagrid/domain.hpp"
#include "viennagrid/config/simplex.hpp"
#include "viennagrid/io/netgen_reader.hpp"
#include "viennagrid/io/vtk_writer.hpp"

//Point-based algorithms:
#include "viennagrid/algorithm/cross_prod.hpp"
#include "viennagrid/algorithm/inner_prod.hpp"
#include "viennagrid/algorithm/norm.hpp"
#include "viennagrid/algorithm/spanned_volume.hpp"

//Cell-based algorithms:
#include "viennagrid/algorithm/centroid.hpp"
#include "viennagrid/algorithm/circumcenter.hpp"
#include "viennagrid/algorithm/surface.hpp"
#include "viennagrid/algorithm/volume.hpp"

//Domain-based algorithms:
#include "viennagrid/algorithm/boundary.hpp"
#include "viennagrid/algorithm/refine.hpp"
#include "viennagrid/algorithm/voronoi.hpp"

int main()
{
  typedef viennagrid::config::tetrahedral_3d                       ConfigType;
  typedef viennagrid::result_of::domain<ConfigType>::type         Domain;
  typedef ConfigType::cell_tag                                    CellTag;

  typedef viennagrid::result_of::point<ConfigType>::type          PointType;
  typedef viennagrid::result_of::ncell<ConfigType, 0>::type       VertexType;
  typedef viennagrid::result_of::ncell<ConfigType, 1>::type       EdgeType;
  typedef viennagrid::result_of::ncell<ConfigType,
                                       CellTag::dim>::type   CellType;

  typedef viennagrid::result_of::ncell_range<Domain, 0>::type                          VertexRange;
  typedef viennagrid::result_of::ncell_range<Domain, CellTag::dim>::type    CellRange;

  std::cout << "------------------------------------------------------------ " << std::endl;
  std::cout << "-- ViennaGrid tutorial: Algorithms on points and elements -- " << std::endl;
  std::cout << "------------------------------------------------------------ " << std::endl;
  std::cout << std::endl;

  Domain domain;

  //
  // Read domain from Netgen file
  //
  try
  {
    viennagrid::io::netgen_reader reader;
    #ifdef _MSC_VER      //Visual Studio builds in a subfolder
    reader(domain, "../../examples/data/cube48.mesh");
    #else
    reader(domain, "../examples/data/cube48.mesh");
    #endif
  }
  catch (std::exception & e)
  {
    std::cout << "Error reading Netgen mesh file: " << std::endl;
    std::cout << e.what() << std::endl;
    return EXIT_FAILURE;
  }

  //
  // Part 1: Point-based algorithms:
  //

  // Extract the first four points of the domain:
  VertexRange vertices = viennagrid::ncells(domain);
  PointType const & p0 = vertices[0].point();
  PointType const & p1 = vertices[1].point();
  PointType const & p2 = vertices[2].point();
  PointType const & p3 = vertices[3].point();

  std::cout << "Point p0: " << p0 << std::endl;
  std::cout << "Point p1: " << p1 << std::endl;
  std::cout << "Point p2: " << p2 << std::endl;
  std::cout << "Point p3: " << p3 << std::endl;

  // Run a few algorithms:
  std::cout << "Cross-product of p1 and p2: " << viennagrid::cross_prod(p1, p2) << std::endl;
  std::cout << "Inner product of p1 and p2: " << viennagrid::inner_prod(p1, p2) << std::endl;
  std::cout << "1-Norm of p2: "               << viennagrid::norm_1(p2) << std::endl;
  std::cout << "2-Norm of p2: "               << viennagrid::norm_2(p2) << std::endl;
  std::cout << "Inf-Norm of p2: "             << viennagrid::norm_inf(p2) << std::endl;
  std::cout << "Length of line [p0, p1]: "    << viennagrid::spanned_volume(p0, p1) << std::endl;
  std::cout << "Area of triangle [p0, p1, p2]: " << viennagrid::spanned_volume(p0, p1, p2) << std::endl;
  std::cout << "Volume of tetrahedron [p0, p1, p2, p3]: " << viennagrid::spanned_volume(p0, p1, p2, p3) << std::endl;

  std::cout << std::endl << "--------------------------------" << std::endl << std::endl;

  //
  // Part 2: Cell-based algorithms:
  //

  // Extract first cell from domain:
  CellType const & cell = viennagrid::ncells<CellTag::dim>(domain)[0];

  std::cout << "cell: " << std::endl << cell << std::endl;

  // Run algorithms:
  std::cout << "Centroid of cell: "     << viennagrid::centroid(cell) << std::endl;
  std::cout << "Circumcenter of cell: " << viennagrid::circumcenter(cell) << std::endl;
  std::cout << "Surface of cell: "      << viennagrid::surface(cell) << std::endl;
  std::cout << "Volume of cell: "       << viennagrid::volume(cell) << std::endl;
  std::cout << std::endl;

  //
  // Part 3: Domain-based algorithms (except interfaces. Refer to the multi-segment tutorial multi_segment.cpp)
  //

  //
  // Write Voronoi info to default ViennaData keys:
  viennagrid::apply_voronoi(domain);

  // Write Voronoi info again, this time using custom keys
  std::string interface_area_key = "voronoi_interface";
  std::string box_volume_key = "voronoi_volume";
  viennagrid::apply_voronoi(domain, interface_area_key, box_volume_key);

  std::cout << "Voronoi box volume at first vertex: "
            << viennadata::access<std::string, double>(box_volume_key)(vertices[0])
            << std::endl;

  //
  // Refine domain uniformly:
  Domain uniformly_refined_domain = viennagrid::refine_uniformly(domain);
  //Domain uniformly_refined_domain = viennagrid::refine(domain, viennagrid::uniform_refinement_tag()); //equivalent to previous line

  //
  // Adaptive refinement: Tag first three cells in domain for refinement
  CellRange cells = viennagrid::ncells<CellTag::dim>(domain);
  viennadata::access<viennagrid::refinement_key, bool>()(cells[0]) = true;
  viennadata::access<viennagrid::refinement_key, bool>()(cells[1]) = true;
  viennadata::access<viennagrid::refinement_key, bool>()(cells[2]) = true;
  Domain adaptively_refined_domain = viennagrid::refine(domain, viennagrid::local_refinement_tag());
  //Domain adaptively_refined_domain = viennagrid::refine_adaptively(domain);  //equivalent to previous line

  viennagrid::io::vtk_writer<Domain> writer;
  writer(uniformly_refined_domain, "uniform_refinement");
  writer(adaptively_refined_domain, "local_refinement");

  //
  // Get boundary information of first vertex with respect to the full domain:
  std::cout << "Boundary flag of first vertex with respect to domain: "
            << viennagrid::is_boundary(vertices[0], domain)    //second argument is the enclosing complex (either a domain or a segment)
            << std::endl << std::endl;

  std::cout << "-----------------------------------------------" << std::endl;
  std::cout << " \\o/    Tutorial finished successfully!    \\o/ " << std::endl;
  std::cout << "-----------------------------------------------" << std::endl;

  return EXIT_SUCCESS;
}
<commit_msg>started to adapt to new domain classes, work in progress!<commit_after>/* =======================================================================
   Copyright (c) 2011, Institute for Microelectronics,
                       Institute for Analysis and Scientific Computing,
                       TU Wien.

                            -----------------
                     ViennaGrid - The Vienna Grid Library
                            -----------------

   Authors:      Karl Rupp                           rupp@iue.tuwien.ac.at
                 Josef Weinbub                    weinbub@iue.tuwien.ac.at

   (A list of additional contributors can be found in the PDF manual)

   License:      MIT (X11), see file LICENSE in the base directory
======================================================================= */

#ifdef _MSC_VER      //Visual Studio complains about potentially dangerous things, which are perfectly legal in our context
  #pragma warning( disable : 4355 )     //use of this in member initializer list
  #pragma warning( disable : 4503 )     //truncated name decoration
#endif

#include "viennagrid/forwards.hpp"
#include "viennagrid/domain.hpp"
#include "viennagrid/config/simplex.hpp"
#include "viennagrid/io/netgen_reader.hpp"
#include "viennagrid/io/vtk_writer.hpp"

//Point-based algorithms:
#include "viennagrid/algorithm/cross_prod.hpp"
#include "viennagrid/algorithm/inner_prod.hpp"
#include "viennagrid/algorithm/norm.hpp"
#include "viennagrid/algorithm/spanned_volume.hpp"

//Cell-based algorithms:
#include "viennagrid/algorithm/centroid.hpp"
#include "viennagrid/algorithm/circumcenter.hpp"
#include "viennagrid/algorithm/surface.hpp"
#include "viennagrid/algorithm/volume.hpp"

//Domain-based algorithms:
#include "viennagrid/algorithm/boundary.hpp"
#include "viennagrid/algorithm/refine.hpp"
#include "viennagrid/algorithm/voronoi.hpp"

#include <typeinfo>

int main()
{

  typedef viennagrid::point_t<double, viennagrid::cartesian_cs<3> > PointType;

  typedef viennagrid::result_of::geometric_domain_config< viennagrid::tetrahedron_tag, PointType, viennagrid::storage::pointer_hook_tag >::type DomainConfig;
  typedef viennagrid::result_of::geometric_domain< DomainConfig >::type Domain;

  typedef viennagrid::result_of::geometric_view<Domain>::type View;

  typedef viennagrid::tetrahedron_tag CellTag;

  typedef viennagrid::result_of::element<Domain, viennagrid::tetrahedron_tag>::type    CellType;
  typedef viennagrid::result_of::element<Domain, viennagrid::triangle_tag>::type       TriangleType;
  typedef viennagrid::result_of::element<Domain, viennagrid::line_tag>::type           EdgeType;
  typedef viennagrid::result_of::element<Domain, viennagrid::vertex_tag>::type         VertexType;
  typedef viennagrid::result_of::element_hook<Domain, viennagrid::vertex_tag>::type    VertexHookType;

  typedef viennagrid::result_of::ncell_range<Domain, 0>::type       VertexRange;
  typedef viennagrid::result_of::ncell_range<Domain, 3>::type       CellRange;

//   typedef viennagrid::config::tetrahedral_3d                       ConfigType;
//   typedef viennagrid::result_of::domain<ConfigType>::type         Domain;
//   typedef ConfigType::cell_tag                                    CellTag;
//
//   typedef viennagrid::result_of::point<ConfigType>::type          PointType;
//   typedef viennagrid::result_of::ncell<ConfigType, 0>::type       VertexType;
//   typedef viennagrid::result_of::ncell<ConfigType, 1>::type       EdgeType;
//   typedef viennagrid::result_of::ncell<ConfigType,
//                                        CellTag::dim>::type   CellType;
//
//   typedef viennagrid::result_of::ncell_range<Domain, 0>::type                          VertexRange;
//   typedef viennagrid::result_of::ncell_range<Domain, CellTag::dim>::type    CellRange;

  std::cout << "------------------------------------------------------------ " << std::endl;
  std::cout << "-- ViennaGrid tutorial: Algorithms on points and elements -- " << std::endl;
  std::cout << "------------------------------------------------------------ " << std::endl;
  std::cout << std::endl;

  Domain domain;
  std::vector<View> segments;

  //
  // Read domain from Netgen file
  //
  try
  {
    viennagrid::io::netgen_reader<CellType> reader;
    #ifdef _MSC_VER      //Visual Studio builds in a subfolder
    reader(domain, segments, "../../examples/data/cube48.mesh");
    #else
    reader(domain, segments, "../examples/data/cube48.mesh");
    #endif
  }
  catch (std::exception & e)
  {
    std::cout << "Error reading Netgen mesh file: " << std::endl;
    std::cout << e.what() << std::endl;
    return EXIT_FAILURE;
  }

  //
  // Part 1: Point-based algorithms:
  //

  // Extract the first four points of the domain:
  VertexRange vertices = viennagrid::ncells<0>(domain);

  PointType const & p0 = viennagrid::point(domain, vertices[0]);
  PointType const & p1 = viennagrid::point(domain, vertices[1]);
  PointType const & p2 = viennagrid::point(domain, vertices[2]);
  PointType const & p3 = viennagrid::point(domain, vertices[3]);

  std::cout << "Point p0: " << p0 << std::endl;
  std::cout << "Point p1: " << p1 << std::endl;
  std::cout << "Point p2: " << p2 << std::endl;
  std::cout << "Point p3: " << p3 << std::endl;

  // Run a few algorithms:
  std::cout << "Cross-product of p1 and p2: " << viennagrid::cross_prod(p1, p2) << std::endl;
  std::cout << "Inner product of p1 and p2: " << viennagrid::inner_prod(p1, p2) << std::endl;
  std::cout << "1-Norm of p2: "               << viennagrid::norm_1(p2) << std::endl;
  std::cout << "2-Norm of p2: "               << viennagrid::norm_2(p2) << std::endl;
  std::cout << "Inf-Norm of p2: "             << viennagrid::norm_inf(p2) << std::endl;
  std::cout << "Length of line [p0, p1]: "    << viennagrid::spanned_volume(p0, p1) << std::endl;
  std::cout << "Area of triangle [p0, p1, p2]: " << viennagrid::spanned_volume(p0, p1, p2) << std::endl;
  std::cout << "Volume of tetrahedron [p0, p1, p2, p3]: " << viennagrid::spanned_volume(p0, p1, p2, p3) << std::endl;

  std::cout << std::endl << "--------------------------------" << std::endl << std::endl;

  //
  // Part 2: Cell-based algorithms:
  //

  // Extract first cell from domain:
  CellType const & cell = viennagrid::elements<CellTag>(domain)[0];

  std::cout << "cell: " << std::endl << cell << std::endl;

  // Run algorithms:
  std::cout << "Centroid of cell: "     << viennagrid::centroid(cell, domain) << std::endl;
  std::cout << "Circumcenter of cell: " << viennagrid::circumcenter(cell, domain) << std::endl;
  std::cout << "Surface of cell: "      << viennagrid::surface(cell, domain) << std::endl;
  std::cout << "Volume of cell: "       << viennagrid::volume(cell, domain) << std::endl;
  std::cout << std::endl;

  std::cout << "Volume of domain: "       << viennagrid::volume<viennagrid::tetrahedron_tag>(domain) << std::endl;
  std::cout << "Surface of domain: "       << viennagrid::surface<viennagrid::tetrahedron_tag>(domain) << std::endl;

  //
  // Part 3: Domain-based algorithms (except interfaces. Refer to the multi-segment tutorial multi_segment.cpp)
  //

  //
  // Write Voronoi info to default ViennaData keys:
  viennagrid::apply_voronoi<CellType>(domain);

  // Write Voronoi info again, this time using custom keys
  std::string interface_area_key = "voronoi_interface";
  std::string box_volume_key = "voronoi_volume";
  viennagrid::apply_voronoi<CellType>(domain, interface_area_key, box_volume_key);

  std::cout << "Voronoi box volume at first vertex: "
            << viennadata::access<std::string, double>(box_volume_key)(vertices[0])
            << std::endl;

  //
  // Refine domain uniformly:
  //Domain uniformly_refined_domain = viennagrid::refine_uniformly(domain);
  //Domain uniformly_refined_domain = viennagrid::refine(domain, viennagrid::uniform_refinement_tag()); //equivalent to previous line

  //
  // Adaptive refinement: Tag first three cells in domain for refinement
  CellRange cells = viennagrid::elements<CellTag>(domain);
  viennadata::access<viennagrid::refinement_key, bool>()(cells[0]) = true;
  viennadata::access<viennagrid::refinement_key, bool>()(cells[1]) = true;
  viennadata::access<viennagrid::refinement_key, bool>()(cells[2]) = true;
  //Domain adaptively_refined_domain = viennagrid::refine<CellTag>(domain, viennagrid::local_refinement_tag());
  //Domain adaptively_refined_domain = viennagrid::refine_adaptively(domain);  //equivalent to previous line

//   viennagrid::io::vtk_writer<Domain> writer;
//   writer(uniformly_refined_domain, "uniform_refinement");
//   writer(adaptively_refined_domain, "local_refinement");

  //
  // Get boundary information of first vertex with respect to the full domain:
  std::cout << "Boundary flag of first vertex with respect to domain: "
            << viennagrid::is_boundary(vertices[0], domain)    //second argument is the enclosing complex (either a domain or a segment)
            << std::endl << std::endl;

  std::cout << "-----------------------------------------------" << std::endl;
  std::cout << " \\o/    Tutorial finished successfully!    \\o/ " << std::endl;
  std::cout << "-----------------------------------------------" << std::endl;

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>// Copyright 2014 Vladimir Alyamkin. All Rights Reserved.

#include "VaRestPluginPrivatePCH.h"

FString UVaRestParseManager::ParseURL(TEXT("https://api.parse.com/1/"));
FString UVaRestParseManager::ParseAppId(TEXT(""));
FString UVaRestParseManager::ParseApiKey(TEXT(""));

UVaRestParseManager::UVaRestParseManager(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{

}

UVaRestParseManager* UVaRestParseManager::ConstructParseRequest(
	UObject* WorldContextObject,
	ERequestVerb::Type Verb,
	ERequestContentType::Type ContentType)
{
	return (UVaRestParseManager*)ConstructRequestExt(WorldContextObject, Verb, ContentType);
}

void UVaRestParseManager::ProcessParseURL(
	const FString& ParseModule,
	const FString& ParseClass,
	const FString& ParseObjectId,
	const FString& ParseSessionToken)
{
	FString RequestUrl = ParseURL;

	// Build the full request url
	if (!ParseModule.IsEmpty())
	{
		RequestUrl += ParseModule;

		if (!ParseClass.IsEmpty())
		{
			RequestUrl += "/" + ParseClass;

			if (!ParseObjectId.IsEmpty())
			{
				RequestUrl += "/" + ParseObjectId;
			}
		}
	}

	TSharedRef<IHttpRequest> HttpRequest = FHttpModule::Get().CreateRequest();
	HttpRequest->SetURL(RequestUrl);

	HttpRequest->SetHeader("X-Parse-Application-Id", ParseAppId);
	HttpRequest->SetHeader("X-Parse-REST-API-Key", ParseApiKey);

	if (!ParseSessionToken.IsEmpty())
	{
		HttpRequest->SetHeader("X-Parse-Session-Token", ParseSessionToken);
	}

	ProcessRequest(HttpRequest);
}

void UVaRestParseManager::SetParseAuthData(FString AppId, FString ApiKey)
{
	ParseAppId = AppId;
	ParseApiKey = ApiKey;
}

//////////////////////////////////////////////////////////////////////////
// Quering helpers

FString UVaRestParseManager::ConstructPointer(const FString& ClassName, const FString& ObjectId)
{
	return FString::Printf(TEXT("{\"__type\":\"Pointer\",\"className\":\"%s\",\"objectId\":\"%s\"}"), *ClassName, *ObjectId);
}

FString UVaRestParseManager::ConstructWhereQuerySimple(const FString& Key, const FString& Value)
{
	return FString::Printf(TEXT("where={\"%s\":%s}"), *Key, *Value);
}

FString UVaRestParseManager::ConstructWhereQuery(UVaRestJsonObject* JsonObject)
{
	// Serialize json data to string
	FString OutputString;
	TSharedRef< TJsonWriter<> > Writer = TJsonWriterFactory<>::Create(&OutputString);
	FJsonSerializer::Serialize(JsonObject->GetRootObject().ToSharedRef(), Writer);

	return TEXT("where=") + OutputString;
}

FString UVaRestParseManager::GetHappyMessage()
{
	return FString("Happy New Year!");
}
<commit_msg>- parse object id is appended to the end of the request even if no class is defined<commit_after>// Copyright 2014 Vladimir Alyamkin. All Rights Reserved.

#include "VaRestPluginPrivatePCH.h"

FString UVaRestParseManager::ParseURL(TEXT("https://api.parse.com/1/"));
FString UVaRestParseManager::ParseAppId(TEXT(""));
FString UVaRestParseManager::ParseApiKey(TEXT(""));

UVaRestParseManager::UVaRestParseManager(const class FPostConstructInitializeProperties& PCIP)
	: Super(PCIP)
{

}

UVaRestParseManager* UVaRestParseManager::ConstructParseRequest(
	UObject* WorldContextObject,
	ERequestVerb::Type Verb,
	ERequestContentType::Type ContentType)
{
	return (UVaRestParseManager*)ConstructRequestExt(WorldContextObject, Verb, ContentType);
}

void UVaRestParseManager::ProcessParseURL(
	const FString& ParseModule,
	const FString& ParseClass,
	const FString& ParseObjectId,
	const FString& ParseSessionToken)
{
	FString RequestUrl = ParseURL;

	// Build the full request url
	if (!ParseModule.IsEmpty())
	{
		RequestUrl += ParseModule;

		if (!ParseClass.IsEmpty())
		{
			RequestUrl += "/" + ParseClass;
		}

		if (!ParseObjectId.IsEmpty())
		{
			RequestUrl += "/" + ParseObjectId;
		}
	}

	TSharedRef<IHttpRequest> HttpRequest = FHttpModule::Get().CreateRequest();
	HttpRequest->SetURL(RequestUrl);

	HttpRequest->SetHeader("X-Parse-Application-Id", ParseAppId);
	HttpRequest->SetHeader("X-Parse-REST-API-Key", ParseApiKey);

	if (!ParseSessionToken.IsEmpty())
	{
		HttpRequest->SetHeader("X-Parse-Session-Token", ParseSessionToken);
	}

	ProcessRequest(HttpRequest);
}

void UVaRestParseManager::SetParseAuthData(FString AppId, FString ApiKey)
{
	ParseAppId = AppId;
	ParseApiKey = ApiKey;
}

//////////////////////////////////////////////////////////////////////////
// Quering helpers

FString UVaRestParseManager::ConstructPointer(const FString& ClassName, const FString& ObjectId)
{
	return FString::Printf(TEXT("{\"__type\":\"Pointer\",\"className\":\"%s\",\"objectId\":\"%s\"}"), *ClassName, *ObjectId);
}

FString UVaRestParseManager::ConstructWhereQuerySimple(const FString& Key, const FString& Value)
{
	return FString::Printf(TEXT("where={\"%s\":%s}"), *Key, *Value);
}

FString UVaRestParseManager::ConstructWhereQuery(UVaRestJsonObject* JsonObject)
{
	// Serialize json data to string
	FString OutputString;
	TSharedRef< TJsonWriter<> > Writer = TJsonWriterFactory<>::Create(&OutputString);
	FJsonSerializer::Serialize(JsonObject->GetRootObject().ToSharedRef(), Writer);

	return TEXT("where=") + OutputString;
}

FString UVaRestParseManager::GetHappyMessage()
{
	return FString("Happy New Year!");
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: seqstream.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: kz $ $Date: 2004-10-04 21:07:12 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _COMPHELPER_SEQSTREAM_HXX
#include <comphelper/seqstream.hxx>
#endif

#include <memory.h> // for memcpy

namespace comphelper
{
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::uno;
using namespace ::osl;

//---------------------------------------------------------------------------------------------
// class SequenceInputStream
//---------------------------------------------------------------------------------------------

//------------------------------------------------------------------
SequenceInputStream::SequenceInputStream(const ByteSequence& rData)
:   m_aData(rData)
,   m_nPos(0)
{
}

// checks if closed, returns available size, not mutex-protected
//------------------------------------------------------------------
inline sal_Int32 SequenceInputStream::avail()
{
    if (m_nPos == -1)
        throw NotConnectedException(::rtl::OUString(), *this);

    return m_aData.getLength() - m_nPos;
}

// com::sun::star::io::XInputStream
//------------------------------------------------------------------
sal_Int32 SAL_CALL SequenceInputStream::readBytes( Sequence<sal_Int8>& aData, sal_Int32 nBytesToRead )
    throw(NotConnectedException, BufferSizeExceededException,
          IOException, RuntimeException)
{
    ::osl::MutexGuard aGuard( m_aMutex );

    sal_Int32 nAvail = avail();

    if (nBytesToRead < 0)
        throw BufferSizeExceededException(::rtl::OUString(),*this);

    if (nAvail < nBytesToRead)
        nBytesToRead = nAvail;

    aData.realloc(nBytesToRead);
    memcpy(aData.getArray(), m_aData.getConstArray() + m_nPos, nBytesToRead);
    m_nPos += nBytesToRead;

    return nBytesToRead;
}

//------------------------------------------------------------------
sal_Int32 SAL_CALL SequenceInputStream::readSomeBytes( Sequence<sal_Int8>& aData, sal_Int32 nMaxBytesToRead )
    throw(NotConnectedException, BufferSizeExceededException,
          IOException, RuntimeException)
{
    // all data is available at once
    return readBytes(aData, nMaxBytesToRead);
}

//------------------------------------------------------------------
void SAL_CALL SequenceInputStream::skipBytes( sal_Int32 nBytesToSkip )
    throw(NotConnectedException, BufferSizeExceededException,
          IOException, RuntimeException)
{
    ::osl::MutexGuard aGuard( m_aMutex );

    sal_Int32 nAvail = avail();

    if (nBytesToSkip < 0)
        throw BufferSizeExceededException(::rtl::OUString(),*this);

    if (nAvail < nBytesToSkip)
        nBytesToSkip = nAvail;

    m_nPos += nBytesToSkip;
}

//------------------------------------------------------------------
sal_Int32 SAL_CALL SequenceInputStream::available(  )
    throw(NotConnectedException, IOException, RuntimeException)
{
    ::osl::MutexGuard aGuard( m_aMutex );

    return avail();
}

//------------------------------------------------------------------
void SAL_CALL SequenceInputStream::closeInput(  )
    throw(NotConnectedException, IOException, RuntimeException)
{
    if (m_nPos == -1)
        throw NotConnectedException(::rtl::OUString(), *this);

    m_nPos = -1;
}

void SAL_CALL SequenceInputStream::seek( sal_Int64 location ) throw (IllegalArgumentException, IOException, RuntimeException)
{
    if ( location > m_aData.getLength()-1 || location < 0 || location > SAL_MAX_INT32 )
        throw IllegalArgumentException();
    m_nPos = (sal_Int32) location;
}

sal_Int64 SAL_CALL SequenceInputStream::getPosition() throw (IOException, RuntimeException)
{
    return m_nPos;
}

sal_Int64 SAL_CALL SequenceInputStream::getLength(  ) throw (IOException, RuntimeException)
{
    return m_aData.getLength();
}

//--------------------------------------------------------------------------
OSequenceOutputStream::OSequenceOutputStream(Sequence< sal_Int8 >& _rSeq, double _nResizeFactor, sal_Int32 _nMinimumResize, sal_Int32 _nMaximumResize)
    :m_rSequence(_rSeq)
    ,m_nResizeFactor(_nResizeFactor)
    ,m_nMinimumResize(_nMinimumResize)
    ,m_nMaximumResize(_nMaximumResize)
    ,m_nSize(0) // starting at position 0
    ,m_bConnected(sal_True)
{
    OSL_ENSURE(m_nResizeFactor > 1, "OSequenceOutputStream::OSequenceOutputStream : invalid resize factor !");
    OSL_ENSURE((m_nMaximumResize < 0) || (m_nMaximumResize > m_nMinimumResize),
        "OSequenceOutputStream::OSequenceOutputStream : these limits don't make any sense !");

    if (m_nResizeFactor <= 1)
        m_nResizeFactor = 1.3;
    if ((m_nMaximumResize >= 0) && (m_nMaximumResize <= m_nMinimumResize))
        m_nMaximumResize = m_nMinimumResize * 2;
        // this heuristic is as good as any other ... supply better parameters if you don't like it :)
}

//--------------------------------------------------------------------------
void SAL_CALL OSequenceOutputStream::writeBytes( const Sequence< sal_Int8 >& _rData ) throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
{
    MutexGuard aGuard(m_aMutex);
    if (!m_bConnected)
        throw NotConnectedException();

    // ensure the sequence has enoungh space left
    if (m_nSize + _rData.getLength() > m_rSequence.getLength())
    {
        sal_Int32 nCurrentLength = m_rSequence.getLength();
        sal_Int32 nNewLength = nCurrentLength * m_nResizeFactor;

        if (m_nMinimumResize > nNewLength - nCurrentLength)
            // we have a minimum so it's not too inefficient for small sequences and small write requests
            nNewLength = nCurrentLength + m_nMinimumResize;

        if ((m_nMaximumResize > 0) && (nNewLength - nCurrentLength > m_nMaximumResize))
            // such a large step is not allowed
            nNewLength = nCurrentLength + m_nMaximumResize;

        if (nNewLength < m_nSize + _rData.getLength())
        {   // it's not enough .... the data would not fit

            // let's take the double amount of the length of the data to be written, as the next write
            // request could be as large as this one
            sal_Int32 nNewGrowth = _rData.getLength() * 2;
            if ((m_nMaximumResize > 0) && (nNewGrowth > m_nMaximumResize))
            {   // we came to the limit, again ...
                nNewGrowth = m_nMaximumResize;
                if (nNewGrowth + nCurrentLength < m_nSize + _rData.getLength())
                    // but it would not fit if we respect the limit
                    nNewGrowth = m_nSize + _rData.getLength() - nCurrentLength;
            }
            nNewLength = nCurrentLength + nNewGrowth;
        }

        // round it off to the next multiple of 4 ...
        nNewLength = (nNewLength + 3) / 4 * 4;

        m_rSequence.realloc(nNewLength);
    }

    OSL_ENSURE(m_rSequence.getLength() >= m_nSize + _rData.getLength(),
        "ooops ... the realloc algorithm seems to be wrong :( !");

    memcpy(m_rSequence.getArray() + m_nSize, _rData.getConstArray(), _rData.getLength());
    m_nSize += _rData.getLength();
}

//--------------------------------------------------------------------------
void SAL_CALL OSequenceOutputStream::flush(  ) throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
{
    MutexGuard aGuard(m_aMutex);
    if (!m_bConnected)
        throw NotConnectedException();

    // nothing to do here
}

//--------------------------------------------------------------------------
void SAL_CALL OSequenceOutputStream::closeOutput(  ) throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
{
    MutexGuard aGuard(m_aMutex);
    if (!m_bConnected)
        throw NotConnectedException();

    // cut the sequence to the real size
    m_rSequence.realloc(m_nSize);
    // and don't allow any further accesses
    m_bConnected = sal_False;
}

} // namespace comphelper
<commit_msg>INTEGRATION: CWS ooo19126 (1.5.116); FILE MERGED 2005/09/05 15:24:13 rt 1.5.116.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: seqstream.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 03:01:05 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _COMPHELPER_SEQSTREAM_HXX
#include <comphelper/seqstream.hxx>
#endif

#include <memory.h> // for memcpy

namespace comphelper
{
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::io;
using namespace ::com::sun::star::uno;
using namespace ::osl;

//---------------------------------------------------------------------------------------------
// class SequenceInputStream
//---------------------------------------------------------------------------------------------

//------------------------------------------------------------------
SequenceInputStream::SequenceInputStream(const ByteSequence& rData)
:   m_aData(rData)
,   m_nPos(0)
{
}

// checks if closed, returns available size, not mutex-protected
//------------------------------------------------------------------
inline sal_Int32 SequenceInputStream::avail()
{
    if (m_nPos == -1)
        throw NotConnectedException(::rtl::OUString(), *this);

    return m_aData.getLength() - m_nPos;
}

// com::sun::star::io::XInputStream
//------------------------------------------------------------------
sal_Int32 SAL_CALL SequenceInputStream::readBytes( Sequence<sal_Int8>& aData, sal_Int32 nBytesToRead )
    throw(NotConnectedException, BufferSizeExceededException,
          IOException, RuntimeException)
{
    ::osl::MutexGuard aGuard( m_aMutex );

    sal_Int32 nAvail = avail();

    if (nBytesToRead < 0)
        throw BufferSizeExceededException(::rtl::OUString(),*this);

    if (nAvail < nBytesToRead)
        nBytesToRead = nAvail;

    aData.realloc(nBytesToRead);
    memcpy(aData.getArray(), m_aData.getConstArray() + m_nPos, nBytesToRead);
    m_nPos += nBytesToRead;

    return nBytesToRead;
}

//------------------------------------------------------------------
sal_Int32 SAL_CALL SequenceInputStream::readSomeBytes( Sequence<sal_Int8>& aData, sal_Int32 nMaxBytesToRead )
    throw(NotConnectedException, BufferSizeExceededException,
          IOException, RuntimeException)
{
    // all data is available at once
    return readBytes(aData, nMaxBytesToRead);
}

//------------------------------------------------------------------
void SAL_CALL SequenceInputStream::skipBytes( sal_Int32 nBytesToSkip )
    throw(NotConnectedException, BufferSizeExceededException,
          IOException, RuntimeException)
{
    ::osl::MutexGuard aGuard( m_aMutex );

    sal_Int32 nAvail = avail();

    if (nBytesToSkip < 0)
        throw BufferSizeExceededException(::rtl::OUString(),*this);

    if (nAvail < nBytesToSkip)
        nBytesToSkip = nAvail;

    m_nPos += nBytesToSkip;
}

//------------------------------------------------------------------
sal_Int32 SAL_CALL SequenceInputStream::available(  )
    throw(NotConnectedException, IOException, RuntimeException)
{
    ::osl::MutexGuard aGuard( m_aMutex );

    return avail();
}

//------------------------------------------------------------------
void SAL_CALL SequenceInputStream::closeInput(  )
    throw(NotConnectedException, IOException, RuntimeException)
{
    if (m_nPos == -1)
        throw NotConnectedException(::rtl::OUString(), *this);

    m_nPos = -1;
}

void SAL_CALL SequenceInputStream::seek( sal_Int64 location ) throw (IllegalArgumentException, IOException, RuntimeException)
{
    if ( location > m_aData.getLength()-1 || location < 0 || location > SAL_MAX_INT32 )
        throw IllegalArgumentException();
    m_nPos = (sal_Int32) location;
}

sal_Int64 SAL_CALL SequenceInputStream::getPosition() throw (IOException, RuntimeException)
{
    return m_nPos;
}

sal_Int64 SAL_CALL SequenceInputStream::getLength(  ) throw (IOException, RuntimeException)
{
    return m_aData.getLength();
}

//--------------------------------------------------------------------------
OSequenceOutputStream::OSequenceOutputStream(Sequence< sal_Int8 >& _rSeq, double _nResizeFactor, sal_Int32 _nMinimumResize, sal_Int32 _nMaximumResize)
    :m_rSequence(_rSeq)
    ,m_nResizeFactor(_nResizeFactor)
    ,m_nMinimumResize(_nMinimumResize)
    ,m_nMaximumResize(_nMaximumResize)
    ,m_nSize(0) // starting at position 0
    ,m_bConnected(sal_True)
{
    OSL_ENSURE(m_nResizeFactor > 1, "OSequenceOutputStream::OSequenceOutputStream : invalid resize factor !");
    OSL_ENSURE((m_nMaximumResize < 0) || (m_nMaximumResize > m_nMinimumResize),
        "OSequenceOutputStream::OSequenceOutputStream : these limits don't make any sense !");

    if (m_nResizeFactor <= 1)
        m_nResizeFactor = 1.3;
    if ((m_nMaximumResize >= 0) && (m_nMaximumResize <= m_nMinimumResize))
        m_nMaximumResize = m_nMinimumResize * 2;
        // this heuristic is as good as any other ... supply better parameters if you don't like it :)
}

//--------------------------------------------------------------------------
void SAL_CALL OSequenceOutputStream::writeBytes( const Sequence< sal_Int8 >& _rData ) throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
{
    MutexGuard aGuard(m_aMutex);
    if (!m_bConnected)
        throw NotConnectedException();

    // ensure the sequence has enoungh space left
    if (m_nSize + _rData.getLength() > m_rSequence.getLength())
    {
        sal_Int32 nCurrentLength = m_rSequence.getLength();
        sal_Int32 nNewLength = nCurrentLength * m_nResizeFactor;

        if (m_nMinimumResize > nNewLength - nCurrentLength)
            // we have a minimum so it's not too inefficient for small sequences and small write requests
            nNewLength = nCurrentLength + m_nMinimumResize;

        if ((m_nMaximumResize > 0) && (nNewLength - nCurrentLength > m_nMaximumResize))
            // such a large step is not allowed
            nNewLength = nCurrentLength + m_nMaximumResize;

        if (nNewLength < m_nSize + _rData.getLength())
        {   // it's not enough .... the data would not fit

            // let's take the double amount of the length of the data to be written, as the next write
            // request could be as large as this one
            sal_Int32 nNewGrowth = _rData.getLength() * 2;
            if ((m_nMaximumResize > 0) && (nNewGrowth > m_nMaximumResize))
            {   // we came to the limit, again ...
                nNewGrowth = m_nMaximumResize;
                if (nNewGrowth + nCurrentLength < m_nSize + _rData.getLength())
                    // but it would not fit if we respect the limit
                    nNewGrowth = m_nSize + _rData.getLength() - nCurrentLength;
            }
            nNewLength = nCurrentLength + nNewGrowth;
        }

        // round it off to the next multiple of 4 ...
        nNewLength = (nNewLength + 3) / 4 * 4;

        m_rSequence.realloc(nNewLength);
    }

    OSL_ENSURE(m_rSequence.getLength() >= m_nSize + _rData.getLength(),
        "ooops ... the realloc algorithm seems to be wrong :( !");

    memcpy(m_rSequence.getArray() + m_nSize, _rData.getConstArray(), _rData.getLength());
    m_nSize += _rData.getLength();
}

//--------------------------------------------------------------------------
void SAL_CALL OSequenceOutputStream::flush(  ) throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
{
    MutexGuard aGuard(m_aMutex);
    if (!m_bConnected)
        throw NotConnectedException();

    // nothing to do here
}

//--------------------------------------------------------------------------
void SAL_CALL OSequenceOutputStream::closeOutput(  ) throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
{
    MutexGuard aGuard(m_aMutex);
    if (!m_bConnected)
        throw NotConnectedException();

    // cut the sequence to the real size
    m_rSequence.realloc(m_nSize);
    // and don't allow any further accesses
    m_bConnected = sal_False;
}

} // namespace comphelper
<|endoftext|>


<commit_before>#include "RepairPartitioningPrototype.h"
using namespace std;

void RepairPartitioningPrototype::printIDtoWordMapping(unordered_map<unsigned, string>& IDsToWords, ostream& os)
{
	for (unordered_map<unsigned, string>::iterator it = IDsToWords.begin(); it != IDsToWords.end(); it++)
	{
		os << it->first << ": " << it->second << endl;
	}
}

void RepairPartitioningPrototype::writeAssociations(const vector<Association>& associations, ostream& os)
{
	for (size_t i = 0; i < associations.size(); i++)
	{
		os << associations[i];
	}
}

double RepairPartitioningPrototype::runRepairPartitioning(
	vector<vector<unsigned> > versions,
	unordered_map<unsigned, string>& IDsToWords,
	unsigned*& offsetsAllVersions,
	unsigned*& versionPartitionSizes,
	vector<Association>& associations,
	unsigned minFragSize,
	float fragmentationCoefficient,
	unsigned repairStoppingPoint,
	unsigned numLevelsDown,
	unsigned method,
	bool printFragments,
	bool printAssociations)
{
	RepairAlgorithm repairAlg(versions);

	repairAlg.run();

	vector<VersionDataItem> versionData = repairAlg.getVersionData();

	associations = repairAlg.getAssociations();

	// Use the result of repair to get a partitioning of the document
	// Hopefully this partitioning gives us fragments that occur many times
	RepairDocumentPartition partition = RepairDocumentPartition(versionData, associations, numLevelsDown, minFragSize, fragmentationCoefficient, method);

	// The offsets that define fragments, for all versions [v0:f0 v0:f1 v0:f2 v1:f0 v1:f1 v2:f0 v2:f1 ...]
	offsetsAllVersions = partition.getOffsets();

	// The number of fragments in each version
	versionPartitionSizes = partition.getVersionSizes();

	string outputFilename = "./Output/results.txt";

	partition.writeResults(versions, IDsToWords, outputFilename, printFragments, printAssociations);

	if (printAssociations)
	{
		cerr << "*** Associations (symbol -> pair) ***" << endl;
		writeAssociations(associations, cerr);
	}

	stringstream command;
	command << "start " << outputFilename.c_str();
	system(command.str().c_str());

	// repairAlg.cleanup();

	return partition.getScore();
}

double RepairPartitioningPrototype::runRepairPartitioning(
	vector<vector<unsigned> > versions,
	unsigned*& offsetsAllVersions,
	unsigned*& versionPartitionSizes,
	vector<Association>& associations,
	unsigned minFragSize,
	float fragmentationCoefficient,
	unsigned method)
{
	RepairAlgorithm repairAlg(versions);

	repairAlg.run();

	vector<VersionDataItem> versionData = repairAlg.getVersionData();

	associations = repairAlg.getAssociations();

	// Use the result of repair to get a partitioning of the document
	// Hopefully this partitioning gives us fragments that occur many times
	RepairDocumentPartition partition = RepairDocumentPartition(versionData, associations,
		1, minFragSize, fragmentationCoefficient, method);

	// The offsets that define fragments, for all versions [v0:f0 v0:f1 v0:f2 v1:f0 v1:f1 v2:f0 v2:f1 ...]
	offsetsAllVersions = partition.getOffsets();

	// The number of fragments in each version
	versionPartitionSizes = partition.getVersionSizes();

	string outputFilename = "./Output/results.txt";

	partition.writeResults(versions, IDsToWords, outputFilename, false, false);

	// if (printAssociations)
	// {
	// 	cerr << "*** Associations (symbol -> pair) ***" << endl;
	// 	writeAssociations(associations, cerr);
	// }

	// stringstream command;
	// command << "start " << outputFilename.c_str();
	// system(command.str().c_str());

	repairAlg.cleanup();

	return partition.getScore();
}

int RepairPartitioningPrototype::run(int argc, char* argv[])
{
	//createOutputDir();

	//heap, repair
	string test = "repair";

	if (test == "heap")
	{
		RandomHeapTest test = RandomHeapTest(1000);
		exit(0);
	}

	if (test == "repair")
	{
		Profiler::getInstance().start("all");
		string inputFilepath = "./Input/ints/";

		/*
		Initial tests show that minFragSize should be proportional to document size
		*/
		unsigned minFragSize = 10; //in words

		/*
		Initial tests show that repairStoppingPoint shouldn't be too small (repair goes too far for our purposes in this case)
		And it shouldn't be larger than the number of versions (this is trivial, we expect to get repetition
		at most numVersions times for inter-version repetitions)
		*/
		unsigned repairStoppingPoint = 1; //pairs that occur less than this amount of times will not be replaced

		/* To what extent are we willing to fragment? See the partitioning algorithm for how this is used */
		float fragmentationCoefficient = 1.0;

		/* A variable used in the primitive way to partition the tree: just go n levels down */
		unsigned numLevelsDown = 3;

		/* The partitioning alg to use. See Partitioning.h for the enum */
		unsigned method = 0;

		if (argc == 2 && (string) argv[1] == "help")
		{
			cerr << "Usage:" << endl;
			cerr << "\t" << argv[0] << " <directory> <fragmentationCoefficient> <minFragSize> <method>" << endl;
			cerr << "\t" << argv[0] << " <directory> <fragmentationCoefficient> <minFragSize>" << endl;
			cerr << "\t" << argv[0] << " <directory> <fragmentationCoefficient>" << endl;
			cerr << "\t" << argv[0] << " <directory>" << endl;
			cerr << "\t" << argv[0] << "" << endl << endl;

			cerr << "Defaults: " << endl;
			cerr << "\tdirectory: " << inputFilepath << endl;
			cerr << "\tfragmentationCoefficient: " << fragmentationCoefficient << endl;
			cerr << "\tminFragSize: " << minFragSize << endl;
			cerr << "\tmethod: " << method << endl;
			exit(0);
		}

		if (argc > 1)
			inputFilepath = (string)argv[1];

		if (argc > 2)
			fragmentationCoefficient = atof(argv[2]);

		if (argc > 3)
			minFragSize = atoi(argv[3]);

		if (argc > 4)
			method = atoi(argv[4]);

		// if (argc > 3)
		// 	repairStoppingPoint = atoi(argv[3]);

		vector<string> inputFilenames = vector<string>();
		if (getFileNames(inputFilepath, inputFilenames))
			return errno;

		char* text;

		int fileSize;

		vector<vector<unsigned> > versions = vector<vector<unsigned> >(); //each inner vector is the wordIDs for one version

		vector<unsigned> wordIDs;

		unordered_map<unsigned, string> IDsToWords = unordered_map<unsigned, string>();

		unordered_map<unsigned, unsigned> uniqueWordIDs = unordered_map<unsigned, unsigned>();

		for (unsigned i = 0; i < inputFilenames.size(); i++)
		{
			stringstream filenameSS;
			filenameSS << inputFilepath << inputFilenames[i];
			string filename = filenameSS.str();
			text = getText(filename, fileSize);
			if (!text)
				continue;
			wordIDs = stringToWordIDs(text, IDsToWords, uniqueWordIDs);

			if (false)
			{
				cerr << "Version " << i << endl;
				for (unsigned j = 0; j < wordIDs.size(); j++)
				{
					cerr << wordIDs[j] << ",";
				}
				cerr << endl << endl;
			}

			versions.push_back(wordIDs);
			delete text;
			text = NULL;
		}

		// By this time, IDsToWords should contain the mappings of IDs to words in all versions
		// printIDtoWordMapping(IDsToWords);
		// system("pause");

		vector<Association> associations;

		unsigned* offsetsAllVersions(NULL);
		unsigned* versionPartitionSizes(NULL);

		double score;
		/* Both overloads are shown below for testing. Just change the bool to switch. */
		if (false)
		{
			score = runRepairPartitioning(versions, IDsToWords,
				offsetsAllVersions, versionPartitionSizes,
				associations, minFragSize,
				fragmentationCoefficient,
				repairStoppingPoint, numLevelsDown,
				method, true, false);
		}
		else
		{
			score = runRepairPartitioning(versions, offsetsAllVersions,
				versionPartitionSizes,
				associations,
				minFragSize,
				fragmentationCoefficient,
				method);
		}

		return score;
	}
}<commit_msg>uncomment file with results output<commit_after>#include "RepairPartitioningPrototype.h"
using namespace std;

void RepairPartitioningPrototype::printIDtoWordMapping(unordered_map<unsigned, string>& IDsToWords, ostream& os)
{
	for (unordered_map<unsigned, string>::iterator it = IDsToWords.begin(); it != IDsToWords.end(); it++)
	{
		os << it->first << ": " << it->second << endl;
	}
}

void RepairPartitioningPrototype::writeAssociations(const vector<Association>& associations, ostream& os)
{
	for (size_t i = 0; i < associations.size(); i++)
	{
		os << associations[i];
	}
}

double RepairPartitioningPrototype::runRepairPartitioning(
	vector<vector<unsigned> > versions,
	unordered_map<unsigned, string>& IDsToWords,
	unsigned*& offsetsAllVersions,
	unsigned*& versionPartitionSizes,
	vector<Association>& associations,
	unsigned minFragSize,
	float fragmentationCoefficient,
	unsigned repairStoppingPoint,
	unsigned numLevelsDown,
	unsigned method,
	bool printFragments,
	bool printAssociations)
{
	RepairAlgorithm repairAlg(versions);

	repairAlg.run();

	vector<VersionDataItem> versionData = repairAlg.getVersionData();

	associations = repairAlg.getAssociations();

	// Use the result of repair to get a partitioning of the document
	// Hopefully this partitioning gives us fragments that occur many times
	RepairDocumentPartition partition = RepairDocumentPartition(versionData, associations, numLevelsDown, minFragSize, fragmentationCoefficient, method);

	// The offsets that define fragments, for all versions [v0:f0 v0:f1 v0:f2 v1:f0 v1:f1 v2:f0 v2:f1 ...]
	offsetsAllVersions = partition.getOffsets();

	// The number of fragments in each version
	versionPartitionSizes = partition.getVersionSizes();

	string outputFilename = "./Output/results.txt";

	partition.writeResults(versions, IDsToWords, outputFilename, printFragments, printAssociations);

	if (printAssociations)
	{
		cerr << "*** Associations (symbol -> pair) ***" << endl;
		writeAssociations(associations, cerr);
	}

	stringstream command;
	command << "start " << outputFilename.c_str();
	system(command.str().c_str());

	// repairAlg.cleanup();

	return partition.getScore();
}

double RepairPartitioningPrototype::runRepairPartitioning(
	vector<vector<unsigned> > versions,
	unsigned*& offsetsAllVersions,
	unsigned*& versionPartitionSizes,
	vector<Association>& associations,
	unsigned minFragSize,
	float fragmentationCoefficient,
	unsigned method)
{
	RepairAlgorithm repairAlg(versions);

	repairAlg.run();

	vector<VersionDataItem> versionData = repairAlg.getVersionData();

	associations = repairAlg.getAssociations();

	// Use the result of repair to get a partitioning of the document
	// Hopefully this partitioning gives us fragments that occur many times
	RepairDocumentPartition partition = RepairDocumentPartition(versionData, associations,
		1, minFragSize, fragmentationCoefficient, method);

	// The offsets that define fragments, for all versions [v0:f0 v0:f1 v0:f2 v1:f0 v1:f1 v2:f0 v2:f1 ...]
	offsetsAllVersions = partition.getOffsets();

	// The number of fragments in each version
	versionPartitionSizes = partition.getVersionSizes();

	string outputFilename = "./Output/results.txt";

	unordered_map<unsigned, string> IDsToWords = unordered_map<unsigned, string>();
	partition.writeResults(versions, IDsToWords, outputFilename, false, false);

	// if (printAssociations)
	// {
	// 	cerr << "*** Associations (symbol -> pair) ***" << endl;
	// 	writeAssociations(associations, cerr);
	// }

	// stringstream command;
	// command << "start " << outputFilename.c_str();
	// system(command.str().c_str());

	repairAlg.cleanup();

	return partition.getScore();
}

int RepairPartitioningPrototype::run(int argc, char* argv[])
{
	//createOutputDir();

	//heap, repair
	string test = "repair";

	if (test == "heap")
	{
		RandomHeapTest test = RandomHeapTest(1000);
		exit(0);
	}

	if (test == "repair")
	{
		Profiler::getInstance().start("all");
		string inputFilepath = "./Input/ints/";

		/*
		Initial tests show that minFragSize should be proportional to document size
		*/
		unsigned minFragSize = 10; //in words

		/*
		Initial tests show that repairStoppingPoint shouldn't be too small (repair goes too far for our purposes in this case)
		And it shouldn't be larger than the number of versions (this is trivial, we expect to get repetition
		at most numVersions times for inter-version repetitions)
		*/
		unsigned repairStoppingPoint = 1; //pairs that occur less than this amount of times will not be replaced

		/* To what extent are we willing to fragment? See the partitioning algorithm for how this is used */
		float fragmentationCoefficient = 1.0;

		/* A variable used in the primitive way to partition the tree: just go n levels down */
		unsigned numLevelsDown = 3;

		/* The partitioning alg to use. See Partitioning.h for the enum */
		unsigned method = 0;

		if (argc == 2 && (string) argv[1] == "help")
		{
			cerr << "Usage:" << endl;
			cerr << "\t" << argv[0] << " <directory> <fragmentationCoefficient> <minFragSize> <method>" << endl;
			cerr << "\t" << argv[0] << " <directory> <fragmentationCoefficient> <minFragSize>" << endl;
			cerr << "\t" << argv[0] << " <directory> <fragmentationCoefficient>" << endl;
			cerr << "\t" << argv[0] << " <directory>" << endl;
			cerr << "\t" << argv[0] << "" << endl << endl;

			cerr << "Defaults: " << endl;
			cerr << "\tdirectory: " << inputFilepath << endl;
			cerr << "\tfragmentationCoefficient: " << fragmentationCoefficient << endl;
			cerr << "\tminFragSize: " << minFragSize << endl;
			cerr << "\tmethod: " << method << endl;
			exit(0);
		}

		if (argc > 1)
			inputFilepath = (string)argv[1];

		if (argc > 2)
			fragmentationCoefficient = atof(argv[2]);

		if (argc > 3)
			minFragSize = atoi(argv[3]);

		if (argc > 4)
			method = atoi(argv[4]);

		// if (argc > 3)
		// 	repairStoppingPoint = atoi(argv[3]);

		vector<string> inputFilenames = vector<string>();
		if (getFileNames(inputFilepath, inputFilenames))
			return errno;

		char* text;

		int fileSize;

		vector<vector<unsigned> > versions = vector<vector<unsigned> >(); //each inner vector is the wordIDs for one version

		vector<unsigned> wordIDs;

		unordered_map<unsigned, string> IDsToWords = unordered_map<unsigned, string>();

		unordered_map<unsigned, unsigned> uniqueWordIDs = unordered_map<unsigned, unsigned>();

		for (unsigned i = 0; i < inputFilenames.size(); i++)
		{
			stringstream filenameSS;
			filenameSS << inputFilepath << inputFilenames[i];
			string filename = filenameSS.str();
			text = getText(filename, fileSize);
			if (!text)
				continue;
			wordIDs = stringToWordIDs(text, IDsToWords, uniqueWordIDs);

			if (false)
			{
				cerr << "Version " << i << endl;
				for (unsigned j = 0; j < wordIDs.size(); j++)
				{
					cerr << wordIDs[j] << ",";
				}
				cerr << endl << endl;
			}

			versions.push_back(wordIDs);
			delete text;
			text = NULL;
		}

		// By this time, IDsToWords should contain the mappings of IDs to words in all versions
		// printIDtoWordMapping(IDsToWords);
		// system("pause");

		vector<Association> associations;

		unsigned* offsetsAllVersions(NULL);
		unsigned* versionPartitionSizes(NULL);

		double score;
		/* Both overloads are shown below for testing. Just change the bool to switch. */
		if (false)
		{
			score = runRepairPartitioning(versions, IDsToWords,
				offsetsAllVersions, versionPartitionSizes,
				associations, minFragSize,
				fragmentationCoefficient,
				repairStoppingPoint, numLevelsDown,
				method, true, false);
		}
		else
		{
			score = runRepairPartitioning(versions, offsetsAllVersions,
				versionPartitionSizes,
				associations,
				minFragSize,
				fragmentationCoefficient,
				method);
		}

		return score;
	}
}<|endoftext|>