<commit_before>//
//  OscClient.cpp
//  show
//
//  Created by Chris Mullany on 02/09/2015.
//
//

#include "OscClient.h"

#define PLAY_SCENE_ADRESS "/scene/playscene"
#define PLAY_SUBSCENE_ADRESS "/scene/playsubscene"
#define PRESENCE_ADRESS "/tracking/presence"
#define VOLUME_ADRESS "/window/volume"
#define VOLUME_TRIGGER_ADRESS "/window/volumetrigger"

OscClient::OscClient() {
    sendAddress = "192.168.0.255";
    sendPort = "12345";
    receivePort = "12345";
    current_msg_string = 0;
}

void OscClient::setup(int id) {
    this->id = id;
}

void OscClient::update() {
    // hide old messages
    for(int i = 0; i < NUM_MSG_STRINGS; i++){
        if(timers[i] < ofGetElapsedTimef()){
            msg_strings[i] = "";
        }
    }

    // check for waiting messages
    while(receiver.hasWaitingMessages()){
        // get the next message
        ofxOscMessage m;
        receiver.getNextMessage(&m);
        string msg_string;
        msg_string = m.getAddress();

        if (msg_string == PLAY_SCENE_ADRESS) {
            int sceneId = m.getArgAsInt32(0);
            int senderId = m.getArgAsInt32(1);
            if (senderId != this->id) ofNotifyEvent(playSceneEvent, sceneId, this);
        }
        else if (msg_string == PLAY_SUBSCENE_ADRESS) {
            int sceneId = m.getArgAsInt32(0);
            int senderId = m.getArgAsInt32(1);
            if (senderId != this->id) ofNotifyEvent(playSubSceneEvent, sceneId, this);
        }
        else if (msg_string == VOLUME_ADRESS) {
            float volume = m.getArgAsFloat(0);
            int windowId = m.getArgAsInt32(1);
            int senderId = m.getArgAsInt32(2);
            VolumeEventArgs args = VolumeEventArgs(volume, windowId);
            if (senderId != this->id) ofNotifyEvent(volumeEvent, args, this);
        }
        else if (msg_string == VOLUME_TRIGGER_ADRESS) {
            int windowId = m.getArgAsInt32(0);
            int senderId = m.getArgAsInt32(1);
            VolumeEventArgs args = VolumeEventArgs(1, windowId);
            if (senderId != this->id) ofNotifyEvent(volumeTriggerEvent, args, this);
        }

        msg_string += ": ";
        for(int i = 0; i < m.getNumArgs(); i++){
            // get the argument type
            msg_string += m.getArgTypeName(i);
            msg_string += ":";
            // display the argument - make sure we get the right type
            if(m.getArgType(i) == OFXOSC_TYPE_INT32){
                msg_string += ofToString(m.getArgAsInt32(i));
            }
            else if(m.getArgType(i) == OFXOSC_TYPE_FLOAT){
                msg_string += ofToString(m.getArgAsFloat(i));
            }
            else if(m.getArgType(i) == OFXOSC_TYPE_STRING){
                msg_string += m.getArgAsString(i);
            }
            else{
                msg_string += "unknown";
            }
        }
        // add to the list of strings to display
        msg_strings[current_msg_string] = msg_string;
        timers[current_msg_string] = ofGetElapsedTimef() + 5.0f;
        current_msg_string = (current_msg_string + 1) % NUM_MSG_STRINGS;
        // clear the next line
        msg_strings[current_msg_string] = "";
    }
}

void OscClient::draw() {
    for(int i = 0; i < NUM_MSG_STRINGS; i++){
        ofDrawBitmapString(msg_strings[i], 10, 40 + 15 * i);
    }
}

//////////////////////////////////////////////////////////////////////////////////
// public
//////////////////////////////////////////////////////////////////////////////////

void OscClient::setupGui() {
    guiName = "OSC";
    panel.setup(guiName, "settings/osc.xml");
    panel.add(info.set("to change", "Edit XML + restart"));
    panel.add(sendAddress.set("to IP", "192.168.0.255"));
    panel.add(sendPort.set("to port", "12345"));
    panel.loadFromFile("settings/osc.xml");
    // setup OSC clients after loading settings
    sender.setup(sendAddress, ofToInt(sendPort));
    receiver.setup(ofToInt(receivePort));
}

void OscClient::sendPlayScene(int id) {
    ofLogNotice("OscClient::sendPlayScene: " + (string)PLAY_SCENE_ADRESS + " " + ofToString(id));
    ofxOscMessage m;
    m.setAddress(PLAY_SCENE_ADRESS);
    m.addIntArg(id);
    m.addIntArg(this->id);
    sender.sendMessage(m);
}

void OscClient::sendPlaySubScene(int id) {
    ofLogNotice("OscClient::sendPlaySubScene: " + (string)PLAY_SUBSCENE_ADRESS + " " + ofToString(id));
    ofxOscMessage m;
    m.setAddress(PLAY_SUBSCENE_ADRESS);
    m.addIntArg(id);
    m.addIntArg(this->id);
    sender.sendMessage(m);
}

void OscClient::sendPresence(string areaName, int count){
    ofxOscMessage m;
    m.setAddress(PRESENCE_ADRESS);
    m.addStringArg(areaName);
    m.addIntArg(count);
    m.addIntArg(this->id);
    sender.sendMessage(m);
}

void OscClient::sendVolume(float volume, int windowId){
    ofLogVerbose("OscClient::sendVolume: " + (string)VOLUME_ADRESS + " " + ofToString(volume));
    ofxOscMessage m;
    m.setAddress(VOLUME_ADRESS);
    m.addFloatArg(volume);
    m.addIntArg(windowId);
    m.addIntArg(this->id);
    sender.sendMessage(m);
}

void OscClient::sendVolumeTrigger(int windowId) {
    ofLogNotice("OscClient::sendVolumeTrigger: " + (string)VOLUME_ADRESS + " " + ofToString(windowId));
    ofxOscMessage m;
    m.setAddress(VOLUME_TRIGGER_ADRESS);
    m.addIntArg(windowId);
    m.addIntArg(this->id);
    sender.sendMessage(m);
}

void OscClient::sendLightSoundCue(CueParams cue) {
    if (cue.lightCue > 0) {
        sendLightingCue(cue.lightCue, cue.lightList);
    }
    if (cue.soundCue > 0) {
        sendSoundCue(cue.soundCue);
    }
}

void OscClient::sendLightSoundCue(CueWithListParams cue) {
    if (cue.lightCue > 0) {
        sendLightingCue(cue.lightCue, cue.lightList);
    }
    if (cue.soundCue > 0) {
        sendSoundCue(cue.soundCue);
    }
}

void OscClient::sendLightSoundCue(CueWithFloatParams cue) {
    if (cue.lightCue > 0) {
        sendLightingCue(cue.lightCue, cue.lightList);
    }
    if (cue.soundCue > 0) {
        sendSoundCue(cue.soundCue);
    }
}

//
// Send lighting LX cues to nomad lighting desk
// which requires the format /eos/cue/<list number>/<cue number>/fire
//
void OscClient::sendLightingCue(float cue, float list) {
    string address = "/eos/cue/" + ofToString(list) + "/" + ofToString(cue) + "/fire";
    ofLogNotice("OscClient::sendLightingCue: " + address);
    ofxOscMessage m;
    m.setAddress(address);
    sender.sendMessage(m);
}

//
// Send audio cue to QLab Mac
// '/cue/{number}/start'
//
void OscClient::sendSoundCue(float cue) {
    string address = "/cue/" + ofToString(cue) + "/start";
    ofLogNotice("OscClient::sendSoundCue: " + address);
    ofxOscMessage m;
    m.setAddress(address);
    sender.sendMessage(m);
}

//
// Send audio cue to QLab Mac
// '/cue/{number}/start'
//
void OscClient::sendSoundVolume(float id, float volume) {
    string address = "/volume/" + ofToString(id) + "/" + ofToString(volume);
    ofLogVerbose("OscClient::sendSoundVolume: " + address);
    ofxOscMessage m;
    m.setAddress(address);
    sender.sendMessage(m);
}

//////////////////////////////////////////////////////////////////////////////////
// protected
//////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////
// private
//////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////
// custom event handlers
//////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////
// oF event handlers
//////////////////////////////////////////////////////////////////////////////////

void OscClient::keyPressed (int key) {
    if(key == 'p'){
        ofxOscMessage m;
        m.setAddress("/ping");
        m.addIntArg(1);
        sender.sendMessage(m);
    }
}
<commit_msg>comments tidy<commit_after>//
//  OscClient.cpp
//  show
//
//  Created by Chris Mullany on 02/09/2015.
//
//

#include "OscClient.h"

#define PLAY_SCENE_ADRESS "/scene/playscene"
#define PLAY_SUBSCENE_ADRESS "/scene/playsubscene"
#define PRESENCE_ADRESS "/tracking/presence"
#define VOLUME_ADRESS "/window/volume"
#define VOLUME_TRIGGER_ADRESS "/window/volumetrigger"

OscClient::OscClient() {
    sendAddress = "192.168.0.255";
    sendPort = "12345";
    receivePort = "12345";
    current_msg_string = 0;
}

void OscClient::setup(int id) {
    this->id = id;
}

void OscClient::update() {
    // hide old messages
    for(int i = 0; i < NUM_MSG_STRINGS; i++){
        if(timers[i] < ofGetElapsedTimef()){
            msg_strings[i] = "";
        }
    }

    // check for waiting messages
    while(receiver.hasWaitingMessages()){
        // get the next message
        ofxOscMessage m;
        receiver.getNextMessage(&m);
        string msg_string;
        msg_string = m.getAddress();

        if (msg_string == PLAY_SCENE_ADRESS) {
            int sceneId = m.getArgAsInt32(0);
            int senderId = m.getArgAsInt32(1);
            if (senderId != this->id) ofNotifyEvent(playSceneEvent, sceneId, this);
        }
        else if (msg_string == PLAY_SUBSCENE_ADRESS) {
            int sceneId = m.getArgAsInt32(0);
            int senderId = m.getArgAsInt32(1);
            if (senderId != this->id) ofNotifyEvent(playSubSceneEvent, sceneId, this);
        }
        else if (msg_string == VOLUME_ADRESS) {
            float volume = m.getArgAsFloat(0);
            int windowId = m.getArgAsInt32(1);
            int senderId = m.getArgAsInt32(2);
            VolumeEventArgs args = VolumeEventArgs(volume, windowId);
            if (senderId != this->id) ofNotifyEvent(volumeEvent, args, this);
        }
        else if (msg_string == VOLUME_TRIGGER_ADRESS) {
            int windowId = m.getArgAsInt32(0);
            int senderId = m.getArgAsInt32(1);
            VolumeEventArgs args = VolumeEventArgs(1, windowId);
            if (senderId != this->id) ofNotifyEvent(volumeTriggerEvent, args, this);
        }

        msg_string += ": ";
        for(int i = 0; i < m.getNumArgs(); i++){
            // get the argument type
            msg_string += m.getArgTypeName(i);
            msg_string += ":";
            // display the argument - make sure we get the right type
            if(m.getArgType(i) == OFXOSC_TYPE_INT32){
                msg_string += ofToString(m.getArgAsInt32(i));
            }
            else if(m.getArgType(i) == OFXOSC_TYPE_FLOAT){
                msg_string += ofToString(m.getArgAsFloat(i));
            }
            else if(m.getArgType(i) == OFXOSC_TYPE_STRING){
                msg_string += m.getArgAsString(i);
            }
            else{
                msg_string += "unknown";
            }
        }
        // add to the list of strings to display
        msg_strings[current_msg_string] = msg_string;
        timers[current_msg_string] = ofGetElapsedTimef() + 5.0f;
        current_msg_string = (current_msg_string + 1) % NUM_MSG_STRINGS;
        // clear the next line
        msg_strings[current_msg_string] = "";
    }
}

void OscClient::draw() {
    for(int i = 0; i < NUM_MSG_STRINGS; i++){
        ofDrawBitmapString(msg_strings[i], 10, 40 + 15 * i);
    }
}

//////////////////////////////////////////////////////////////////////////////////
// public
//////////////////////////////////////////////////////////////////////////////////

void OscClient::setupGui() {
    guiName = "OSC";
    panel.setup(guiName, "settings/osc.xml");
    panel.add(info.set("to change", "Edit XML + restart"));
    panel.add(sendAddress.set("to IP", "192.168.0.255"));
    panel.add(sendPort.set("to port", "12345"));
    panel.loadFromFile("settings/osc.xml");
    // setup OSC clients after loading settings
    sender.setup(sendAddress, ofToInt(sendPort));
    receiver.setup(ofToInt(receivePort));
}

void OscClient::sendPlayScene(int id) {
    ofLogNotice("OscClient::sendPlayScene: " + (string)PLAY_SCENE_ADRESS + " " + ofToString(id));
    ofxOscMessage m;
    m.setAddress(PLAY_SCENE_ADRESS);
    m.addIntArg(id);
    m.addIntArg(this->id);
    sender.sendMessage(m);
}

void OscClient::sendPlaySubScene(int id) {
    ofLogNotice("OscClient::sendPlaySubScene: " + (string)PLAY_SUBSCENE_ADRESS + " " + ofToString(id));
    ofxOscMessage m;
    m.setAddress(PLAY_SUBSCENE_ADRESS);
    m.addIntArg(id);
    m.addIntArg(this->id);
    sender.sendMessage(m);
}

void OscClient::sendPresence(string areaName, int count){
    ofxOscMessage m;
    m.setAddress(PRESENCE_ADRESS);
    m.addStringArg(areaName);
    m.addIntArg(count);
    m.addIntArg(this->id);
    sender.sendMessage(m);
}

void OscClient::sendVolume(float volume, int windowId){
    ofLogVerbose("OscClient::sendVolume: " + (string)VOLUME_ADRESS + " " + ofToString(volume));
    ofxOscMessage m;
    m.setAddress(VOLUME_ADRESS);
    m.addFloatArg(volume);
    m.addIntArg(windowId);
    m.addIntArg(this->id);
    sender.sendMessage(m);
}

void OscClient::sendVolumeTrigger(int windowId) {
    ofLogNotice("OscClient::sendVolumeTrigger: " + (string)VOLUME_ADRESS + " " + ofToString(windowId));
    ofxOscMessage m;
    m.setAddress(VOLUME_TRIGGER_ADRESS);
    m.addIntArg(windowId);
    m.addIntArg(this->id);
    sender.sendMessage(m);
}

void OscClient::sendLightSoundCue(CueParams cue) {
    if (cue.lightCue > 0) {
        sendLightingCue(cue.lightCue, cue.lightList);
    }
    if (cue.soundCue > 0) {
        sendSoundCue(cue.soundCue);
    }
}

void OscClient::sendLightSoundCue(CueWithListParams cue) {
    if (cue.lightCue > 0) {
        sendLightingCue(cue.lightCue, cue.lightList);
    }
    if (cue.soundCue > 0) {
        sendSoundCue(cue.soundCue);
    }
}

void OscClient::sendLightSoundCue(CueWithFloatParams cue) {
    if (cue.lightCue > 0) {
        sendLightingCue(cue.lightCue, cue.lightList);
    }
    if (cue.soundCue > 0) {
        sendSoundCue(cue.soundCue);
    }
}

//
// Send lighting LX cues to nomad lighting desk
// which requires the format /eos/cue/<list number>/<cue number>/fire
//
void OscClient::sendLightingCue(float cue, float list) {
    string address = "/eos/cue/" + ofToString(list) + "/" + ofToString(cue) + "/fire";
    ofLogNotice("OscClient::sendLightingCue: " + address);
    ofxOscMessage m;
    m.setAddress(address);
    sender.sendMessage(m);
}

//
// Send audio cue to QLab Mac
// '/cue/{number}/start'
//
void OscClient::sendSoundCue(float cue) {
    string address = "/cue/" + ofToString(cue) + "/start";
    ofLogNotice("OscClient::sendSoundCue: " + address);
    ofxOscMessage m;
    m.setAddress(address);
    sender.sendMessage(m);
}

//
// Send audio voluem cue to QLab Mac?
// '/volume/{number}/start'??
//
void OscClient::sendSoundVolume(float id, float volume) {
    string address = "/volume/" + ofToString(id) + "/" + ofToString(volume);
    ofLogVerbose("OscClient::sendSoundVolume: " + address);
    ofxOscMessage m;
    m.setAddress(address);
    sender.sendMessage(m);
}

//////////////////////////////////////////////////////////////////////////////////
// protected
//////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////
// private
//////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////
// custom event handlers
//////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////
// oF event handlers
//////////////////////////////////////////////////////////////////////////////////

void OscClient::keyPressed (int key) {
    if(key == 'p'){
        ofxOscMessage m;
        m.setAddress("/ping");
        m.addIntArg(1);
        sender.sendMessage(m);
    }
}
<|endoftext|>


<commit_before>
//第一个（完全用static变量进行控制）

unsigned char RD(int i,int j)
{
	static double k;
	k+=rand()/1./RAND_MAX;
	int l=k;
	l%=512;
	return l>255?511-l:l;
}

unsigned char GR(int i,int j)
{
	static double k;
	k+=rand()/1./RAND_MAX;
	int l=k;
	l%=512;
	return l>255?511-l:l;
}

unsigned char BL(int i,int j)
{
	static double k;
	k+=rand()/1./RAND_MAX;
	int l=k;
	l%=512;
	return l>255?511-l:l;
}

//第二个（三角函数弄得我头晕）
unsigned char RD(int i,int j)
{
  return (char)(_sq(cos(atan2(j-512,i-512)/2))*255);
}

unsigned char GR(int i,int j)
{
  return (char)(_sq(cos(atan2(j-512,i-512)/2-2*acos(-1)/3))*255);
}

unsigned char BL(int i,int j)
{
  return (char)(_sq(cos(atan2(j-512,i-512)/2+2*acos(-1)/3))*255);

}

//嘿嘿，我自己的
unsigned char RD(int i,int j)
{
  return (i)%256;
}

unsigned char GR(int i,int j)
{
  return (j)/4%256;
}

unsigned char BL(int i,int j)
{
  return (i+j)/4%256;
}

//第三个 棋盘
unsigned char RD(int i,int j)
{
  return BL(i,j)*2;
  #define t(m,n)_sq(m)+_sq(n)
  #define z(m,n)t(m*32-i,n*32-j)
  #define q(m,n,k)if(z(m,n)<196)return k*255;if(z(m,n)<225)return 0;
}

unsigned char GR(int i,int j)
{
  BL(i,j);
}

unsigned char BL(int i,int j)
{
  q(16,16,1)q(15,16,0)q(16,15,0)q(17,16,0)q(16,17,0)
  return(i&31)&&(j&31)?80:0;
}

//分形几何
unsigned char RD(int i,int j)
{
	float x=0,y=0;
	int k;
	for(k=0;k++<256;)
	{
		float a=x*x-y*y+(i-768.0)/512;
		y=2*x*y+(j-512.0)/512;
		x=a;
		if(x*x+y*y>4)
			break;
	}
	return log(k)*47;
}

unsigned char GR(int i,int j)
{
	float x=0,y=0;
	int k;
	for(k=0;k++<256;)
	{
		float a=x*x-y*y+(i-768.0)/512;
		y=2*x*y+(j-512.0)/512;
		x=a;
		if(x*x+y*y>4)break;
	}
	return log(k)*47;
}

unsigned char BL(int i,int j)
{
	float x=0,y=0;
	int k;
	for(k=0;k++<256;)
	{
		float a=x*x-y*y+(i-768.0)/512;
		y=2*x*y+(j-512.0)/512;
		x=a;
		if(x*x+y*y>4)break;
	}
	return 128-log(k)*23;
}

//放大镜效果
unsigned short RD(int i,int j){
#define F(x) float x
#define R return
#define Ci (DIM/2)
#define Cj Ci
#define Z (Ci/2)
#define G (Ci/8)
#define N 3
R BL(i,j);
}

unsigned short GR(int i,int j){
#define Y(x) sqrt(1.-_sq(x))
R BL(i,j);
}

unsigned short BL(int i,int j){
F(r)=sqrt(0.+_sq(i-Ci)+_sq(j-Cj));F(s)=r/Z;if(s<1){i-=Ci;j-=Cj;F(k)=(Y(s)*Y(s/N)+_sq(s)/N)*N;i=i/k+Ci;j=j/k+Cj;}R (i/G+j/G)%2*255;
}

//油画效果
unsigned char RD(int i,int j){
#define r(n)(rand()%n)
static char c[1024][1024];return!c[i][j]?c[i][j]=!r(999)?r(256):RD((i+r(2))%1024,(j+r(2))%1024):c[i][j];
}

unsigned char GR(int i,int j){
static char c[1024][1024];return!c[i][j]?c[i][j]=!r(999)?r(256):GR((i+r(2))%1024,(j+r(2))%1024):c[i][j];
}

unsigned char BL(int i,int j){
static char c[1024][1024];return!c[i][j]?c[i][j]=!r(999)?r(256):BL((i+r(2))%1024,(j+r(2))%1024):c[i][j];
}

//波浪效果
unsigned char RD(int i,int j){
float s=3./(j+99);
float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s;
return (int((i+DIM)*s+y)%2+int((DIM*2-i)*s+y)%2)*127;
}

unsigned char GR(int i,int j){
float s=3./(j+99);
float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s;
return (int(5*((i+DIM)*s+y))%2+int(5*((DIM*2-i)*s+y))%2)*127;
}

unsigned char BL(int i,int j){
float s=3./(j+99);
float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s;
return (int(29*((i+DIM)*s+y))%2+int(29*((DIM*2-i)*s+y))%2)*127;
}

<commit_msg>添加一个效果代码<commit_after>
//第一个（完全用static变量进行控制）

unsigned char RD(int i,int j)
{
	static double k;
	k+=rand()/1./RAND_MAX;
	int l=k;
	l%=512;
	return l>255?511-l:l;
}

unsigned char GR(int i,int j)
{
	static double k;
	k+=rand()/1./RAND_MAX;
	int l=k;
	l%=512;
	return l>255?511-l:l;
}

unsigned char BL(int i,int j)
{
	static double k;
	k+=rand()/1./RAND_MAX;
	int l=k;
	l%=512;
	return l>255?511-l:l;
}

//第二个（三角函数弄得我头晕）
unsigned char RD(int i,int j)
{
  return (char)(_sq(cos(atan2(j-512,i-512)/2))*255);
}

unsigned char GR(int i,int j)
{
  return (char)(_sq(cos(atan2(j-512,i-512)/2-2*acos(-1)/3))*255);
}

unsigned char BL(int i,int j)
{
  return (char)(_sq(cos(atan2(j-512,i-512)/2+2*acos(-1)/3))*255);

}

//嘿嘿，我自己的
unsigned char RD(int i,int j)
{
  return (i)%256;
}

unsigned char GR(int i,int j)
{
  return (j)/4%256;
}

unsigned char BL(int i,int j)
{
  return (i+j)/4%256;
}

unsigned char RD(int i,int j)
{
	return i&&j?(i%j)&(j%i):0;
}

unsigned char GR(int i,int j)
{
	return i&&j?(i%j)+(j%i):0;
}

unsigned char BL(int i,int j)
{
	return i&&j?(i%j)|(j%i):0;
}

//第三个 棋盘
unsigned char RD(int i,int j)
{
  return BL(i,j)*2;
  #define t(m,n)_sq(m)+_sq(n)
  #define z(m,n)t(m*32-i,n*32-j)
  #define q(m,n,k)if(z(m,n)<196)return k*255;if(z(m,n)<225)return 0;
}

unsigned char GR(int i,int j)
{
  BL(i,j);
}

unsigned char BL(int i,int j)
{
  q(16,16,1)q(15,16,0)q(16,15,0)q(17,16,0)q(16,17,0)
  return(i&31)&&(j&31)?80:0;
}

//分形几何
unsigned char RD(int i,int j)
{
	float x=0,y=0;
	int k;
	for(k=0;k++<256;)
	{
		float a=x*x-y*y+(i-768.0)/512;
		y=2*x*y+(j-512.0)/512;
		x=a;
		if(x*x+y*y>4)
			break;
	}
	return log(k)*47;
}

unsigned char GR(int i,int j)
{
	float x=0,y=0;
	int k;
	for(k=0;k++<256;)
	{
		float a=x*x-y*y+(i-768.0)/512;
		y=2*x*y+(j-512.0)/512;
		x=a;
		if(x*x+y*y>4)break;
	}
	return log(k)*47;
}

unsigned char BL(int i,int j)
{
	float x=0,y=0;
	int k;
	for(k=0;k++<256;)
	{
		float a=x*x-y*y+(i-768.0)/512;
		y=2*x*y+(j-512.0)/512;
		x=a;
		if(x*x+y*y>4)break;
	}
	return 128-log(k)*23;
}

//放大镜效果
unsigned short RD(int i,int j){
#define F(x) float x
#define R return
#define Ci (DIM/2)
#define Cj Ci
#define Z (Ci/2)
#define G (Ci/8)
#define N 3
R BL(i,j);
}

unsigned short GR(int i,int j){
#define Y(x) sqrt(1.-_sq(x))
R BL(i,j);
}

unsigned short BL(int i,int j){
F(r)=sqrt(0.+_sq(i-Ci)+_sq(j-Cj));F(s)=r/Z;if(s<1){i-=Ci;j-=Cj;F(k)=(Y(s)*Y(s/N)+_sq(s)/N)*N;i=i/k+Ci;j=j/k+Cj;}R (i/G+j/G)%2*255;
}

//油画效果
unsigned char RD(int i,int j){
#define r(n)(rand()%n)
static char c[1024][1024];return!c[i][j]?c[i][j]=!r(999)?r(256):RD((i+r(2))%1024,(j+r(2))%1024):c[i][j];
}

unsigned char GR(int i,int j){
static char c[1024][1024];return!c[i][j]?c[i][j]=!r(999)?r(256):GR((i+r(2))%1024,(j+r(2))%1024):c[i][j];
}

unsigned char BL(int i,int j){
static char c[1024][1024];return!c[i][j]?c[i][j]=!r(999)?r(256):BL((i+r(2))%1024,(j+r(2))%1024):c[i][j];
}

//波浪效果
unsigned char RD(int i,int j){
float s=3./(j+99);
float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s;
return (int((i+DIM)*s+y)%2+int((DIM*2-i)*s+y)%2)*127;
}

unsigned char GR(int i,int j){
float s=3./(j+99);
float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s;
return (int(5*((i+DIM)*s+y))%2+int(5*((DIM*2-i)*s+y))%2)*127;
}

unsigned char BL(int i,int j){
float s=3./(j+99);
float y=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s;
return (int(29*((i+DIM)*s+y))%2+int(29*((DIM*2-i)*s+y))%2)*127;
}

<|endoftext|>


<commit_before>#ifndef KA_FUNCTOR_HPP
#define KA_FUNCTOR_HPP
#pragma once
#include "macro.hpp"
#include "macroregular.hpp"
#include "utility.hpp"
#include "functional.hpp"
#include "typetraits.hpp"

/// Defines the `ka::fmap` function that is part of the `Functor` and
/// `FunctorApp` concepts (see `concept.hpp` for the formal definitions). This
/// function is defined for:
///
/// - standard containers (in functorcontainer.hpp)
/// - optionals (in opt.hpp): boost::optional, ka::opt
/// - functions (in functional.hpp): std::function (boost::function's model
///     could be defined in the same way)
/// - any type that defines a member function `fmap` (in this case `ka::fmap`
///   simply forwards to the member function).
///
/// `ka::fmap` is defined as a polymorphic *function object*, that calls a free
/// function `fmap` through `ADL`. The benefits of this approach are that:
///
/// - the caller always write `ka::fmap` (no `using ka::fmap` needed) while
///   `ADL` is still triggered.
/// - as a function object, `ka::fmap` is easy to manipulate (as a member in
///   another type, through function composition, etc.), in contrast to a
///   template function.
///
/// The general approach is taken from Eric Niebler:
/// http://ericniebler.com/2014/10/21/customization-point-design-in-c11-and-beyond/
///
/// `ka::fmap` can also be partially applied resulting in a polymorphic lifted
/// function (see example below).
///
/// Example: Applying a unary function to the elements of a container.
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// // vector<human_t> humans;
/// // mood_t mood(human_t const&);
/// vector<mood_t> moods = ka::fmap(mood, humans);
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///
/// Example: Applying a n-ary function to the elements of several containers
///          (`FunctorApp` concept)
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// // Warning: All containers must have the same number of elements.
/// // vector<human_t> humans;
/// // vector<place_t> places;
/// // memory_t memory_at(human_t const&, place_t const&);
/// vector<memory_t> memories = ka::fmap(memory_at, humans, places);
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///
/// Example: Applying a n-ary function to the value of several optionals
///          (`FunctorApp` concept)
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// // (Of course, it is also possible to apply the function to a single
/// // optional.)
/// // boost::optional<human_t> detected_human;
/// // boost::optional<message_t> pending_message;
/// // mood_t inform(human_t const&, message_t const&);
///
/// // If any input optional is empty, output optional is empty.
/// boost::optional<mood_t> m = ka::fmap(inform, detected_human, pending_message);
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///
/// Example: Applying a unary function to a function
///          (results in function composition).
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// // std::function<human_t (robot_t)> owner;
/// // string name(human_t const&); // Ok with any function object if signatures
/// //                              // match.
/// std::function<string (robot_t)> name_of_owner = ka::fmap(name, owner);
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///
/// Example: Applying the same lifted function to different functors.
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// // int age(human_t const&);
/// // ka::opt_t<human_t> detected_human;
/// // std::map<string, human_t> humans_by_name;
/// // std::function<human_t (event_t)> organizer;
/// auto age_lift = ka::fmap(age);
/// ka::opt_t<int> maybe_age = age_lift(detected_human);
/// std::map<string, int> ages_by_name = age_lift(humans_by_name);
/// std::function<int (event_t)> age_of_organizer = age_lift(organizer);
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// TODO: Remove trailing returns when above C++11. Beware of the distinction
//       between `auto` and `decltype(auto)`.

namespace ka {

namespace fmap_ns {
  // Overloads are defined here and available for `fmap_fn_t`.

  // Type has a member fmap: call it.
  // Function<B (A)> F
  template<typename F, typename T> KA_CONSTEXPR
  auto fmap_dispatch(true_t /* HasMemberFmap<C> */, F&& f, T&& t)
      -> decltype(fwd<T>(t).fmap(fwd<F>(f))) {
    return fwd<T>(t).fmap(fwd<F>(f));
  }

  // Dispatches to the member function if possible.
  // Note: Do not remove the trailing return type as it is needed for SFINAE.
  template<typename F, typename T, typename... U> KA_CONSTEXPR
  auto fmap(F&& f, T&& t, U&&... u)
      -> decltype(fmap_dispatch(HasMemberFmap<Decay<T>>{}, fwd<F>(f), fwd<T>(t), fwd<U>(u)...)) {
    return fmap_dispatch(HasMemberFmap<Decay<T>>{}, fwd<F>(f), fwd<T>(t), fwd<U>(u)...);
  }

  template<typename F>
  struct fmap_bound_t {
    F f;
  // Regular:
    KA_GENERATE_FRIEND_REGULAR_OPS_1(fmap_bound_t, f)
  // Function:
    template<typename T, typename... U> KA_CONSTEXPR
    auto operator()(T&& t, U&&... u) const -> decltype(fmap(f, fwd<T>(t), fwd<U>(u)...)) {
      // Performs ADL.
      return fmap(f, fwd<T>(t), fwd<U>(u)...);
    }
  };

  // Must be defined in this namespace to get access to the overloads.
  struct fmap_fn_t {
  // Regular:
    KA_GENERATE_FRIEND_REGULAR_OPS_0(fmap_fn_t)
  // Function<X<B> (F, X<A>...)>, with Function<B (A...)> F:
    template<typename F, typename T, typename... U> KA_CONSTEXPR
    auto operator()(F&& f, T&& t, U&&... u) const -> decltype(fmap(fwd<F>(f), fwd<T>(t), fwd<U>(u)...)) {
      // Performs ADL.
      return fmap(fwd<F>(f), fwd<T>(t), fwd<U>(u)...);
    }

    // Partial application.
    template<typename F> KA_CONSTEXPR
    auto operator()(F&& f) const -> fmap_bound_t<Decay<F>> {
      return {fwd<F>(f)};
    }
  };
} // namespace fmap_ns

/// Function that calls the `fmap` free function through `ADL`.
///
/// Lookup algorithm:
///   if a `fmap` function is found through `ADL`:
///     call it
///   else if the type has a member `fmap`:
///     call it
///   else if `fmap_dispatch(false_t, F, T...)` is defined:
///     call it (if this specialization comes from `functorcontainer.hpp`, a
///       standard container is assumed)
///
using fmap_ns::fmap_fn_t;

// Avoid ODR violations.
namespace {
  static auto const& fmap = static_const_t<fmap_fn_t>::value;
}

} // namespace ka

#endif // KA_FUNCTOR_HPP
<commit_msg>ka.functor: Makes `fmap` a constexpr variable.<commit_after>#ifndef KA_FUNCTOR_HPP
#define KA_FUNCTOR_HPP
#pragma once
#include "macro.hpp"
#include "macroregular.hpp"
#include "utility.hpp"
#include "functional.hpp"
#include "typetraits.hpp"

/// Defines the `ka::fmap` function that is part of the `Functor` and
/// `FunctorApp` concepts (see `concept.hpp` for the formal definitions). This
/// function is defined for:
///
/// - standard containers (in functorcontainer.hpp)
/// - optionals (in opt.hpp): boost::optional, ka::opt
/// - functions (in functional.hpp): std::function (boost::function's model
///     could be defined in the same way)
/// - any type that defines a member function `fmap` (in this case `ka::fmap`
///   simply forwards to the member function).
///
/// `ka::fmap` is defined as a polymorphic *function object*, that calls a free
/// function `fmap` through `ADL`. The benefits of this approach are that:
///
/// - the caller always write `ka::fmap` (no `using ka::fmap` needed) while
///   `ADL` is still triggered.
/// - as a function object, `ka::fmap` is easy to manipulate (as a member in
///   another type, through function composition, etc.), in contrast to a
///   template function.
///
/// The general approach is taken from Eric Niebler:
/// http://ericniebler.com/2014/10/21/customization-point-design-in-c11-and-beyond/
///
/// `ka::fmap` can also be partially applied resulting in a polymorphic lifted
/// function (see example below).
///
/// Example: Applying a unary function to the elements of a container.
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// // vector<human_t> humans;
/// // mood_t mood(human_t const&);
/// vector<mood_t> moods = ka::fmap(mood, humans);
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///
/// Example: Applying a n-ary function to the elements of several containers
///          (`FunctorApp` concept)
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// // Warning: All containers must have the same number of elements.
/// // vector<human_t> humans;
/// // vector<place_t> places;
/// // memory_t memory_at(human_t const&, place_t const&);
/// vector<memory_t> memories = ka::fmap(memory_at, humans, places);
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///
/// Example: Applying a n-ary function to the value of several optionals
///          (`FunctorApp` concept)
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// // (Of course, it is also possible to apply the function to a single
/// // optional.)
/// // boost::optional<human_t> detected_human;
/// // boost::optional<message_t> pending_message;
/// // mood_t inform(human_t const&, message_t const&);
///
/// // If any input optional is empty, output optional is empty.
/// boost::optional<mood_t> m = ka::fmap(inform, detected_human, pending_message);
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///
/// Example: Applying a unary function to a function
///          (results in function composition).
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// // std::function<human_t (robot_t)> owner;
/// // string name(human_t const&); // Ok with any function object if signatures
/// //                              // match.
/// std::function<string (robot_t)> name_of_owner = ka::fmap(name, owner);
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///
/// Example: Applying the same lifted function to different functors.
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// // int age(human_t const&);
/// // ka::opt_t<human_t> detected_human;
/// // std::map<string, human_t> humans_by_name;
/// // std::function<human_t (event_t)> organizer;
/// auto age_lift = ka::fmap(age);
/// ka::opt_t<int> maybe_age = age_lift(detected_human);
/// std::map<string, int> ages_by_name = age_lift(humans_by_name);
/// std::function<int (event_t)> age_of_organizer = age_lift(organizer);
/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// TODO: Remove trailing returns when above C++11. Beware of the distinction
//       between `auto` and `decltype(auto)`.

namespace ka {

namespace fmap_ns {
  // Overloads are defined here and available for `fmap_fn_t`.

  // Type has a member fmap: call it.
  // Function<B (A)> F
  template<typename F, typename T> KA_CONSTEXPR
  auto fmap_dispatch(true_t /* HasMemberFmap<C> */, F&& f, T&& t)
      -> decltype(fwd<T>(t).fmap(fwd<F>(f))) {
    return fwd<T>(t).fmap(fwd<F>(f));
  }

  // Dispatches to the member function if possible.
  // Note: Do not remove the trailing return type as it is needed for SFINAE.
  template<typename F, typename T, typename... U> KA_CONSTEXPR
  auto fmap(F&& f, T&& t, U&&... u)
      -> decltype(fmap_dispatch(HasMemberFmap<Decay<T>>{}, fwd<F>(f), fwd<T>(t), fwd<U>(u)...)) {
    return fmap_dispatch(HasMemberFmap<Decay<T>>{}, fwd<F>(f), fwd<T>(t), fwd<U>(u)...);
  }

  template<typename F>
  struct fmap_bound_t {
    F f;
  // Regular:
    KA_GENERATE_FRIEND_REGULAR_OPS_1(fmap_bound_t, f)
  // Function:
    template<typename T, typename... U> KA_CONSTEXPR
    auto operator()(T&& t, U&&... u) const -> decltype(fmap(f, fwd<T>(t), fwd<U>(u)...)) {
      // Performs ADL.
      return fmap(f, fwd<T>(t), fwd<U>(u)...);
    }
  };

  // Must be defined in this namespace to get access to the overloads.
  struct fmap_fn_t {
  // Regular:
    KA_GENERATE_FRIEND_REGULAR_OPS_0(fmap_fn_t)
  // Function<X<B> (F, X<A>...)>, with Function<B (A...)> F:
    template<typename F, typename T, typename... U> KA_CONSTEXPR
    auto operator()(F&& f, T&& t, U&&... u) const -> decltype(fmap(fwd<F>(f), fwd<T>(t), fwd<U>(u)...)) {
      // Performs ADL.
      return fmap(fwd<F>(f), fwd<T>(t), fwd<U>(u)...);
    }

    // Partial application.
    template<typename F> KA_CONSTEXPR
    auto operator()(F&& f) const -> fmap_bound_t<Decay<F>> {
      return {fwd<F>(f)};
    }
  };
} // namespace fmap_ns

/// Function that calls the `fmap` free function through `ADL`.
///
/// Lookup algorithm:
///   if a `fmap` function is found through `ADL`:
///     call it
///   else if the type has a member `fmap`:
///     call it
///   else if `fmap_dispatch(false_t, F, T...)` is defined:
///     call it (if this specialization comes from `functorcontainer.hpp`, a
///       standard container is assumed)
///
using fmap_ns::fmap_fn_t;

// Avoid ODR violations.
namespace {
  static constexpr auto const& fmap = static_const_t<fmap_fn_t>::value;
}

} // namespace ka

#endif // KA_FUNCTOR_HPP
<|endoftext|>


<commit_before>#include "types.h"
#include "kernel.hh"
#include "spinlock.h"
#include "condvar.h"
#include "fs.h"
#include "file.hh"
#include "stat.h"
#include "net.hh"

struct devsw __mpalign__ devsw[NDEV];

file*
file::alloc(void)
{
  return new file();
}

file::file(void)
  : rcu_freed("file"),
    type(file::FD_NONE), readable(0), writable(0),
    socket(0), pipe(nullptr), ip(nullptr), off(0)
{
}

void
file::onzero(void) const
{
  if(type == file::FD_PIPE)
    pipeclose(pipe, writable);
  else if(type == file::FD_INODE)
    iput(ip);
  else if(type == file::FD_SOCKET)
    netclose(socket);
  else if(type != file::FD_NONE)
    panic("file::close bad type");
  gc_delayed((file*)this);
}

void
file::do_gc(void)
{
  delete this;
}

file*
file::dup(void)
{
  inc();
  return this;
}

int
file::stat(struct stat *st)
{
  if(type == file::FD_INODE){
    ilock(ip, 0);
    if(ip->type == 0)
      panic("filestat");
    stati(ip, st);
    iunlock(ip);
    return 0;
  }
  return -1;
}

int
file::read(char *addr, int n)
{
  int r;

  if(readable == 0)
    return -1;
  if(type == file::FD_PIPE)
    return piperead(pipe, addr, n);
  if(type == file::FD_INODE){
    ilock(ip, 0);
    if(ip->type == 0)
      panic("fileread");
    if((r = readi(ip, addr, off, n)) > 0)
      off += r;
    iunlock(ip);
    return r;
  }
  if(type == file::FD_SOCKET)
    return netread(socket, addr, n);
  panic("fileread");
}

ssize_t
file::pread(char *addr, size_t n, off_t off)
{
  if(type == file::FD_INODE){
    int r;
    if(ip->type == 0)
      panic("file::pread");
    r = readi(ip, addr, off, n);
    return r;
  }
  return -1;
}

int
file::write(const char *addr, int n)
{
  int r;

  if(writable == 0)
    return -1;
  if(type == file::FD_PIPE)
    return pipewrite(pipe, addr, n);
  if(type == file::FD_INODE){
    ilock(ip, 1);
    if(ip->type == 0 || ip->type == T_DIR)
      panic("filewrite but 0 or T_DIR");
    if((r = writei(ip, addr, off, n)) > 0)
      off += r;
    iunlock(ip);
    return r;
  }
  if(type == file::FD_SOCKET)
    return netwrite(socket, addr, n);
  panic("filewrite");
}

ssize_t
file::pwrite(const char *addr, size_t n, off_t off)
{
  if(type == file::FD_INODE){
    int r;
    ilock(ip, 1);
    if(ip->type == 0 || ip->type == T_DIR)
      panic("filewrite but 0 or T_DIR");
    r = writei(ip, addr, off, n);
    iunlock(ip);
    return r;
  }
  return -1;
}
<commit_msg>Only ilock in pwrite is there's a chance of growing the file<commit_after>#include "types.h"
#include "kernel.hh"
#include "spinlock.h"
#include "condvar.h"
#include "fs.h"
#include "file.hh"
#include "stat.h"
#include "net.hh"

struct devsw __mpalign__ devsw[NDEV];

file*
file::alloc(void)
{
  return new file();
}

file::file(void)
  : rcu_freed("file"),
    type(file::FD_NONE), readable(0), writable(0),
    socket(0), pipe(nullptr), ip(nullptr), off(0)
{
}

void
file::onzero(void) const
{
  if(type == file::FD_PIPE)
    pipeclose(pipe, writable);
  else if(type == file::FD_INODE)
    iput(ip);
  else if(type == file::FD_SOCKET)
    netclose(socket);
  else if(type != file::FD_NONE)
    panic("file::close bad type");
  gc_delayed((file*)this);
}

void
file::do_gc(void)
{
  delete this;
}

file*
file::dup(void)
{
  inc();
  return this;
}

int
file::stat(struct stat *st)
{
  if(type == file::FD_INODE){
    ilock(ip, 0);
    if(ip->type == 0)
      panic("filestat");
    stati(ip, st);
    iunlock(ip);
    return 0;
  }
  return -1;
}

int
file::read(char *addr, int n)
{
  int r;

  if(readable == 0)
    return -1;
  if(type == file::FD_PIPE)
    return piperead(pipe, addr, n);
  if(type == file::FD_INODE){
    ilock(ip, 0);
    if(ip->type == 0)
      panic("fileread");
    if((r = readi(ip, addr, off, n)) > 0)
      off += r;
    iunlock(ip);
    return r;
  }
  if(type == file::FD_SOCKET)
    return netread(socket, addr, n);
  panic("fileread");
}

ssize_t
file::pread(char *addr, size_t n, off_t off)
{
  if(type == file::FD_INODE){
    int r;
    if(ip->type == 0)
      panic("file::pread");
    r = readi(ip, addr, off, n);
    return r;
  }
  return -1;
}

int
file::write(const char *addr, int n)
{
  int r;

  if(writable == 0)
    return -1;
  if(type == file::FD_PIPE)
    return pipewrite(pipe, addr, n);
  if(type == file::FD_INODE){
    ilock(ip, 1);
    if(ip->type == 0 || ip->type == T_DIR)
      panic("filewrite but 0 or T_DIR");
    if((r = writei(ip, addr, off, n)) > 0)
      off += r;
    iunlock(ip);
    return r;
  }
  if(type == file::FD_SOCKET)
    return netwrite(socket, addr, n);
  panic("filewrite");
}

ssize_t
file::pwrite(const char *addr, size_t n, off_t off)
{
  if(type == file::FD_INODE){
    bool unlock;
    int r;

    if(ip->type == 0 || ip->type == T_DIR)
      panic("filewrite but 0 or T_DIR");

    unlock = false;
    if (n+off > ip->size) {
      ilock(ip, 1);
      unlock = true;
    }

    r = writei(ip, addr, off, n);

    if (unlock)
      iunlock(ip);

    return r;
  }
  return -1;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * 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 "otbWrapperChoiceParameter.h"
#include "otbWrapperListViewParameter.h"
#include "otbWrapperBoolParameter.h"
#include "otbWrapperApplicationRegistry.h"
#include "otbWrapperTypes.h"
#include "otbWrapperApplication.h"

#include <vector>
#include <string>
#include <iostream>
#include <cassert>
#include <fstream>

int main(int argc, char* argv[])
{
  if (argc < 3)
    {
      std::cerr << "Usage : " << argv[0] << " name OTB_APPLICATION_PATH [out_dir]" << std::endl;
      return EXIT_FAILURE;
    }

  using namespace otb::Wrapper;

  const std::string module(argv[1]);

  /* TestApplication is removed in CMakeLists.txt */
#if 0
  if (module == "TestApplication")
    return EXIT_SUCCESS;
#endif

  ApplicationRegistry::AddApplicationPath(argv[2]);
  Application::Pointer appli =  ApplicationRegistry::CreateApplicationFaster(module.c_str());

  assert(!appli.IsNull());

  std::map<ParameterType, std::string> parameterTypeToString;

  parameterTypeToString[ParameterType_Empty] = "QgsProcessingParameterBoolean";
  parameterTypeToString[ParameterType_Bool] = "QgsProcessingParameterBoolean";
  parameterTypeToString[ParameterType_Int] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_Float] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_RAM] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_Radius] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_Choice] = "OTBParameterChoice";
  parameterTypeToString[ParameterType_String] = "QgsProcessingParameterString";
  parameterTypeToString[ParameterType_InputImage] = "QgsProcessingParameterRasterLayer";
  parameterTypeToString[ParameterType_InputFilename] = "QgsProcessingParameterFile";
  parameterTypeToString[ParameterType_InputImageList] = "QgsProcessingParameterMultipleLayers";
  parameterTypeToString[ParameterType_InputVectorData] = "QgsProcessingParameterVectorLayer";
  parameterTypeToString[ParameterType_InputFilenameList] = "QgsProcessingParameterMultipleLayers";
  parameterTypeToString[ParameterType_InputVectorDataList] = "QgsProcessingParameterMultipleLayers";
  parameterTypeToString[ParameterType_OutputImage] = "QgsProcessingParameterRasterDestination";
  parameterTypeToString[ParameterType_OutputVectorData] = "QgsProcessingParameterVectorDestination";
  parameterTypeToString[ParameterType_OutputFilename] = "QgsProcessingParameterFileDestination";
  parameterTypeToString[ParameterType_Directory] = "QgsProcessingParameterFile";
  //TODO
  parameterTypeToString[ParameterType_StringList] = "QgsProcessingParameterString";

  //ListView parameters are treated as plain string (QLineEdit) in qgis processing ui.
  //This seems rather unpleasant when comparing Qgis processing with Monteverdi/Mapla in OTB
  //We tried to push something simple with checkboxes but its too risky for this version
  //and clock is ticking...
  //
  parameterTypeToString[ParameterType_ListView] = "QgsProcessingParameterString";

  //For next update of plugin code ListView should use a custom widget wrapper and behave
  //exactly like OTB Mapla. And this #if 0 block is our TODO remainder.
  #if 0
  parameterTypeToString[ParameterType_ListView] = "OTBParameterListView";
  #endif

  const std::vector<std::string> appKeyList = appli->GetParametersKeys(true);
  const unsigned int nbOfParam = appKeyList.size();

  std::string output_file = module + ".txt";
  std::string  algs_txt = "algs.txt";
  if (argc > 3)
    {
      output_file = std::string(argv[3]) + module + ".txt";
      algs_txt = std::string(argv[3])  +  "algs.txt";
    }
  std::ofstream dFile;
  dFile.open (output_file, std::ios::out);
  std::cerr << "Writing " << output_file << std::endl;

  std::string output_parameter_name;
  bool hasRasterOutput = false;
  {
  for (unsigned int i = 0; i < nbOfParam; i++)
    {
      Parameter::Pointer param = appli->GetParameterByKey(appKeyList[i]);
      if (param->GetMandatory())
	{
	  ParameterType type = appli->GetParameterType(appKeyList[i]);
	  if (type == ParameterType_OutputImage )
	    {
	      output_parameter_name = appKeyList[i];
	      hasRasterOutput = true;
	    }
	}
    }

  if(output_parameter_name.empty())
    dFile << module << std::endl;
  else
    dFile << module << "|" <<  output_parameter_name << std::endl;

  dFile << appli->GetDescription() << std::endl;
  const std::string group = appli->GetDocTags().size() > 0 ? appli->GetDocTags()[0] : "UNCLASSIFIED";
  dFile << group << std::endl;

  for (unsigned int i = 0; i < nbOfParam; i++)
    {
      const std::string name = appKeyList[i];

      Parameter::Pointer param = appli->GetParameterByKey(name);
      ParameterType type = appli->GetParameterType(name);
      const std::string description = param->GetName();
      const std::string qgis_type = parameterTypeToString[type];

      if (  type == ParameterType_Group  ||
	    type == ParameterType_OutputProcessXML  ||
	    type == ParameterType_InputProcessXML  ||
	    type == ParameterType_RAM
	    )
	{
	  // group parameter cannot have any value.
	  //outxml and inxml parameters are not relevant for QGIS and is considered a bit noisy
	  //ram is added by qgis-otb processing provider plugin as an advanced parameter for all apps
	  //listview is a special case. We indeed add them to descriptor file but with different logic.
	  continue;
	}

      assert(!qgis_type.empty());
      if(qgis_type.empty())
	{
	  std::cerr << "No mapping found for parameter '" <<name <<"' type=" << type << std::endl;
	  return EXIT_FAILURE;
	}

      bool isDestination = false;

      dFile << qgis_type << "|" << name << "|" << description;

      std::string default_value = "None";
      if (type == ParameterType_Int)
	{
	  dFile << "|QgsProcessingParameterNumber.Integer";
	  default_value = param->HasValue() ? appli->GetParameterAsString(name): "0";
	}
      else if (type == ParameterType_Float)
	{
	  dFile << "|QgsProcessingParameterNumber.Double";
	  default_value = param->HasValue() ? appli->GetParameterAsString(name): "0";
	}
      else if (type == ParameterType_Radius)
	{
	  dFile << "|QgsProcessingParameterNumber.Integer";
	  default_value = param->HasValue() ? appli->GetParameterAsString(name): "0";
	}
      else if(type == ParameterType_InputFilename)
	{
	  dFile << "|QgsProcessingParameterFile.File|txt";
	}
      else if(type == ParameterType_Directory)
	{
	  dFile << "|QgsProcessingParameterFile.Folder|False";
	}
      else if (type == ParameterType_InputImageList)
	{
	   dFile << "|3";
	}
      else if (type == ParameterType_InputVectorDataList)
	{
	  dFile << "|-1";
	}
      else if (type == ParameterType_InputVectorData)
	{
	  dFile << "|-1";
	}
      else if(type == ParameterType_InputFilenameList)
	{
	  dFile << "|4";
	}
      else if (type == ParameterType_InputImage)
	{
	  //default is None and nothing to add to dFile
	}
      else if(type ==ParameterType_String)
	{
	  //default is None and nothing to add to dFile
	}
      else if(type ==ParameterType_StringList)
	{
	  //default is None and nothing to add to dFile
	}
      else if(type ==ParameterType_ListView)
	{
	  //default is None and nothing to add to dFile
	}
      else if(type == ParameterType_Bool)
	{
	  //BoolParameter *bparam = dynamic_cast<BoolParameter*>(param.GetPointer());
	  //default_value = bparam->GetValueAsString();
	  default_value =  appli->GetParameterAsString(name);
	}
      else if(type == ParameterType_Choice)
	{
	  std::vector<std::string>  key_list  = appli->GetChoiceKeys(name);
	  std::string values = "";
	  for( auto k : key_list)
	    values += k + ";";

	  values.pop_back();
	  dFile << "|" << values ;
	  ChoiceParameter *cparam = dynamic_cast<ChoiceParameter*>(param.GetPointer());
	  default_value = std::to_string(cparam->GetValue());
	}
      else if(type == ParameterType_OutputVectorData ||
	      type == ParameterType_OutputImage ||
	      type == ParameterType_OutputFilename)
	{
	  //no need for default_value, optional and extra fields in dFile
	  //if parameter is a destination type. qgis_type|name|description is enough.
	  //so we simply set isDestination to true and skip to end to append a new line.
	  isDestination =  true;
	}
      else
	{
     	  std::cout << "ERROR: default_value is empty for '" << name << "' type='" << qgis_type << "'" << std::endl;
	  return EXIT_FAILURE;
	}

      if (!isDestination)
	{
	  //const char*  optional = param->GetMandatory() ? "False" : "True";
	  std::string optional;
	  if (param->GetMandatory())
	    if (param->HasValue())
	      {
		optional = "True";
	      }
	    else{
	      optional = "False";
	    }
	  else {
	    optional = "True";
	  }

	  dFile << "|" << default_value << "|" << optional;
	}
      dFile << std::endl;
   }

  dFile.close();

  std::ofstream indexFile;
  indexFile.open (algs_txt, std::ios::out | std::ios::app );
  indexFile << group << "|" << module << std::endl;
  indexFile.close();
  return EXIT_SUCCESS;
}

<commit_msg>ENH: cleanup parts of listview<commit_after>/*
 * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * 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 "otbWrapperChoiceParameter.h"
#include "otbWrapperListViewParameter.h"
#include "otbWrapperBoolParameter.h"
#include "otbWrapperApplicationRegistry.h"
#include "otbWrapperTypes.h"
#include "otbWrapperApplication.h"

#include <vector>
#include <string>
#include <iostream>
#include <cassert>
#include <fstream>

int main(int argc, char* argv[])
{
  if (argc < 3)
    {
      std::cerr << "Usage : " << argv[0] << " name OTB_APPLICATION_PATH [out_dir]" << std::endl;
      return EXIT_FAILURE;
    }

  using namespace otb::Wrapper;

  const std::string module(argv[1]);

  /* TestApplication is removed in CMakeLists.txt */
#if 0
  if (module == "TestApplication")
    return EXIT_SUCCESS;
#endif

  ApplicationRegistry::AddApplicationPath(argv[2]);
  Application::Pointer appli =  ApplicationRegistry::CreateApplicationFaster(module.c_str());

  assert(!appli.IsNull());

  std::map<ParameterType, std::string> parameterTypeToString;
  parameterTypeToString[ParameterType_Empty] = "QgsProcessingParameterBoolean";
  parameterTypeToString[ParameterType_Bool] = "QgsProcessingParameterBoolean";
  parameterTypeToString[ParameterType_Int] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_Float] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_RAM] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_Radius] = "QgsProcessingParameterNumber";
  parameterTypeToString[ParameterType_Choice] = "OTBParameterChoice";
  parameterTypeToString[ParameterType_String] = "QgsProcessingParameterString";
  parameterTypeToString[ParameterType_InputImage] = "QgsProcessingParameterRasterLayer";
  parameterTypeToString[ParameterType_InputFilename] = "QgsProcessingParameterFile";
  parameterTypeToString[ParameterType_InputImageList] = "QgsProcessingParameterMultipleLayers";
  parameterTypeToString[ParameterType_InputVectorData] = "QgsProcessingParameterVectorLayer";
  parameterTypeToString[ParameterType_InputFilenameList] = "QgsProcessingParameterMultipleLayers";
  parameterTypeToString[ParameterType_InputVectorDataList] = "QgsProcessingParameterMultipleLayers";
  parameterTypeToString[ParameterType_OutputImage] = "QgsProcessingParameterRasterDestination";
  parameterTypeToString[ParameterType_OutputVectorData] = "QgsProcessingParameterVectorDestination";
  parameterTypeToString[ParameterType_OutputFilename] = "QgsProcessingParameterFileDestination";
  parameterTypeToString[ParameterType_Directory] = "QgsProcessingParameterFile";
  //TODO
  parameterTypeToString[ParameterType_StringList] = "QgsProcessingParameterString";
  //ListView parameters are treated as plain string (QLineEdit) in qgis processing ui.
  //This seems rather unpleasant when comparing Qgis processing with Monteverdi/Mapla in OTB
  //We tried to push something simple with checkboxes but its too risky for this version
  //and clock is ticking...
  //
  parameterTypeToString[ParameterType_ListView] = "QgsProcessingParameterString";

  //For next update of plugin code ListView should use a custom widget wrapper and behave
  //exactly like OTB Mapla. And this #if 0 block is our TODO remainder.
  #if 0
  parameterTypeToString[ParameterType_ListView] = "OTBParameterListView";
  #endif

  const std::vector<std::string> appKeyList = appli->GetParametersKeys(true);
  const unsigned int nbOfParam = appKeyList.size();

  std::string output_file = module + ".txt";
  std::string  algs_txt = "algs.txt";
  if (argc > 3)
    {
      output_file = std::string(argv[3]) + module + ".txt";
      algs_txt = std::string(argv[3])  +  "algs.txt";
    }
  std::ofstream dFile;
  dFile.open (output_file, std::ios::out);
  std::cerr << "Writing " << output_file << std::endl;

  std::string output_parameter_name;
  bool hasRasterOutput = false;
  {
  for (unsigned int i = 0; i < nbOfParam; i++)
    {
      Parameter::Pointer param = appli->GetParameterByKey(appKeyList[i]);
      if (param->GetMandatory())
	{
	  ParameterType type = appli->GetParameterType(appKeyList[i]);
	  if (type == ParameterType_OutputImage )
	    {
	      output_parameter_name = appKeyList[i];
	      hasRasterOutput = true;
	    }
	}
    }
  }

  if(output_parameter_name.empty())
    dFile << module << std::endl;
  else
    dFile << module << "|" <<  output_parameter_name << std::endl;

  dFile << appli->GetDescription() << std::endl;
  const std::string group = appli->GetDocTags().size() > 0 ? appli->GetDocTags()[0] : "UNCLASSIFIED";
  dFile << group << std::endl;

  for (unsigned int i = 0; i < nbOfParam; i++)
    {
      const std::string name = appKeyList[i];

      Parameter::Pointer param = appli->GetParameterByKey(name);
      ParameterType type = appli->GetParameterType(name);
      const std::string description = param->GetName();
      std::string qgis_type = parameterTypeToString[type];
#if 0
      if (type == ParameterType_ListView)
	{
	  ListViewParameter *lv_param = dynamic_cast<ListViewParameter*>(param.GetPointer());
	  std::cerr << "lv_param->GetSingleSelection()" << lv_param->GetSingleSelection() << std::endl;
	  if (lv_param->GetSingleSelection())
	    {

	      qgis_type = "QgsProcessingParameterEnum";
	      std::vector<std::string>  key_list  = appli->GetChoiceKeys(name);
	      std::string values = "";
	      for( auto k : key_list)
		values += k + ";";
	      values.pop_back();
	      dFile << "|" << values ;
	    }
	}
#endif
      if (  type == ParameterType_Group  ||
	    type == ParameterType_OutputProcessXML  ||
	    type == ParameterType_InputProcessXML  ||
	    type == ParameterType_RAM
	    )
	{
	  // group parameter cannot have any value.
	  //outxml and inxml parameters are not relevant for QGIS and is considered a bit noisy
	  //ram is added by qgis-otb processing provider plugin as an advanced parameter for all apps
	  continue;
	}

      assert(!qgis_type.empty());
      if(qgis_type.empty())
	{
	  std::cerr << "No mapping found for parameter '" <<name <<"' type=" << type << std::endl;
	  return EXIT_FAILURE;
	}

      bool isDestination = false;

      dFile << qgis_type << "|" << name << "|" << description;

      std::string default_value = "None";
      if (type == ParameterType_Int)
	{
	  dFile << "|QgsProcessingParameterNumber.Integer";
	  default_value = param->HasValue() ? appli->GetParameterAsString(name): "0";
	}
      else if (type == ParameterType_Float)
	{
	  dFile << "|QgsProcessingParameterNumber.Double";
	  default_value = param->HasValue() ? appli->GetParameterAsString(name): "0";
	}
      else if (type == ParameterType_Radius)
	{
	  dFile << "|QgsProcessingParameterNumber.Integer";
	  default_value = param->HasValue() ? appli->GetParameterAsString(name): "0";
	}
      else if(type == ParameterType_InputFilename)
	{
	  dFile << "|QgsProcessingParameterFile.File|txt";
	}
      else if(type == ParameterType_Directory)
	{
	  dFile << "|QgsProcessingParameterFile.Folder|False";
	}
      else if (type == ParameterType_InputImageList)
	{
	   dFile << "|3";
	}
      else if (type == ParameterType_InputVectorDataList)
	{
	  dFile << "|-1";
	}
      else if (type == ParameterType_InputVectorData)
	{
	  dFile << "|-1";
	}
      else if(type == ParameterType_InputFilenameList)
	{
	  dFile << "|4";
	}
      else if (type == ParameterType_InputImage)
	{
	  //default is None and nothing to add to dFile
	}
      else if(type ==ParameterType_String)
	{
	  //default is None and nothing to add to dFile
	}
      else if(type ==ParameterType_StringList)
	{
	  //default is None and nothing to add to dFile
	}
      else if(type ==ParameterType_ListView)
	{
	  //default is None and nothing to add to dFile
	}
      else if(type == ParameterType_Bool)
	{
	  default_value =  appli->GetParameterAsString(name);
	}
      else if(type == ParameterType_Choice)
	{
	  std::vector<std::string>  key_list  = appli->GetChoiceKeys(name);
	  std::string values = "";
	  for( auto k : key_list)
	    values += k + ";";

	  values.pop_back();
	  dFile << "|" << values ;
	  ChoiceParameter *cparam = dynamic_cast<ChoiceParameter*>(param.GetPointer());
	  default_value = std::to_string(cparam->GetValue());
	}
      else if(type == ParameterType_OutputVectorData ||
	      type == ParameterType_OutputImage ||
	      type == ParameterType_OutputFilename)
	{
	  //no need for default_value, optional and extra fields in dFile
	  //if parameter is a destination type. qgis_type|name|description is enough.
	  //so we simply set isDestination to true and skip to end to append a new line.
	  isDestination =  true;
	}
      else
	{
     	  std::cout << "ERROR: default_value is empty for '" << name << "' type='" << qgis_type << "'" << std::endl;
	  return EXIT_FAILURE;
	}

      if (!isDestination)
	{
	  //const char*  optional = param->GetMandatory() ? "False" : "True";
	  std::string optional;
	  if (param->GetMandatory())
	    if (param->HasValue())
	      {
		optional = "True";
	      }
	    else{
	      optional = "False";
	    }
	  else {
	    optional = "True";
	  }

	  dFile << "|" << default_value << "|" << optional;
	}
      dFile << std::endl;
   }

  dFile.close();

  std::ofstream indexFile;
  indexFile.open (algs_txt, std::ios::out | std::ios::app );
  indexFile << group << "|" << module << std::endl;
  indexFile.close();
  return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>//===--- ClangIncludePaths.cpp --------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "ClangIncludePaths.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsClangImporter.h"
#include "swift/Basic/Platform.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Frontend/CompilerInstance.h"

using namespace swift;

using Path = SmallString<128>;

static Optional<Path> getActualModuleMapPath(StringRef name,
                                             SearchPathOptions &Opts,
                                             const llvm::Triple &triple) {
  StringRef platform = swift::getPlatformNameForTriple(triple);
  StringRef arch = swift::getMajorArchitectureName(triple);

  Path result;

  StringRef SDKPath = Opts.getSDKPath();
  if (!SDKPath.empty()) {
    result.append(SDKPath.begin(), SDKPath.end());
    llvm::sys::path::append(result, "usr", "lib", "swift");
    llvm::sys::path::append(result, platform, arch, name);

    // Only specify the module map if that file actually exists.  It may not;
    // for example in the case that `swiftc -target x86_64-unknown-linux-gnu
    // -emit-ir` is invoked using a Swift compiler not built for Linux targets.
    if (llvm::sys::fs::exists(result))
      return result;
  }

  if (!Opts.RuntimeResourcePath.empty()) {
    result.clear();
    result.append(Opts.RuntimeResourcePath.begin(),
                  Opts.RuntimeResourcePath.end());
    llvm::sys::path::append(result, platform, arch, name);

    // Only specify the module map if that file actually exists.  It may not;
    // for example in the case that `swiftc -target x86_64-unknown-linux-gnu
    // -emit-ir` is invoked using a Swift compiler not built for Linux targets.
    if (llvm::sys::fs::exists(result))
      return result;
  }

  return None;
}

/// Given an include path directory, returns a path to inject the module map to.
/// If a module map already exists, returns `None`.
static llvm::Optional<Path> getInjectedModuleMapPath(const Path &dir) {
  Path legacyPath(dir);
  llvm::sys::path::append(legacyPath, "module.map");
  if (llvm::sys::fs::exists(legacyPath))
    return None;

  Path path(dir);
  llvm::sys::path::append(path, "module.modulemap");
  if (llvm::sys::fs::exists(path))
    return None;

  return path;
}

/// Finds the glibc.modulemap file relative to the provided resource dir.
///
/// Note that the module map used for Glibc depends on the target we're
/// compiling for, and is not included in the resource directory with the other
/// implicit module maps. It's at {freebsd|linux}/{arch}/glibc.modulemap.
static Optional<Path>
getGlibcModuleMapPath(SearchPathOptions &Opts, const llvm::Triple &triple) {
  return getActualModuleMapPath("glibc.modulemap", Opts, triple);
}

static Optional<Path>
getLibStdCxxModuleMapPath(SearchPathOptions &opts, const llvm::Triple &triple) {
  return getActualModuleMapPath("libstdcxx.modulemap", opts, triple);
}

Optional<SmallString<128>>
swift::getCxxShimModuleMapPath(SearchPathOptions &opts,
                               const llvm::Triple &triple) {
  return getActualModuleMapPath("libcxxshim.modulemap", opts, triple);
}

static llvm::opt::InputArgList
parseClangDriverArgs(const clang::driver::Driver &clangDriver,
                     const ArrayRef<const char *> args) {
  unsigned unused1, unused2;
  return clangDriver.getOpts().ParseArgs(args, unused1, unused2);
}

static clang::driver::Driver createClangDriver(const ASTContext &ctx) {
  auto clangDiags = clang::CompilerInstance::createDiagnostics(
      new clang::DiagnosticOptions());
  clang::driver::Driver clangDriver(ctx.ClangImporterOpts.clangPath,
                                    ctx.LangOpts.Target.str(), *clangDiags);
  return clangDriver;
}

/// Given a list of include paths and a list of file names, finds the first
/// include path that contains files with all the names. This is useful for
/// finding the include path for a specific library among a list of include
/// paths.
///
/// \return a path without dots (`../`, './').
static llvm::Optional<Path>
findFirstIncludeDir(const llvm::opt::InputArgList &args,
                    const ArrayRef<const char *> expectedFileNames) {
  // C++ stdlib paths are added as `-internal-isystem`.
  std::vector<std::string> includeDirs =
      args.getAllArgValues(clang::driver::options::OPT_internal_isystem);
  // C stdlib paths are added as `-internal-externc-isystem`.
  llvm::append_range(includeDirs,
                     args.getAllArgValues(
                         clang::driver::options::OPT_internal_externc_isystem));

  for (const auto &includeDir : includeDirs) {
    Path dir(includeDir);
    bool allExpectedExist = true;
    for (auto expectedFileName : expectedFileNames) {
      Path expectedFile(dir);
      llvm::sys::path::append(expectedFile, expectedFileName);
      if (!llvm::sys::fs::exists(expectedFile)) {
        allExpectedExist = false;
        break;
      }
    }

    if (allExpectedExist) {
      // VFS does not allow mapping paths that contain `../` or `./`.
      llvm::sys::path::remove_dots(dir, /*remove_dot_dot=*/true);
      return dir;
    }
  }
  return None;
}

static llvm::opt::InputArgList
createClangArgs(const ASTContext &ctx, clang::driver::Driver &clangDriver) {
  // Flags passed to Swift with `-Xcc` might affect include paths.
  std::vector<const char *> clangArgs;
  for (const auto &each : ctx.ClangImporterOpts.ExtraArgs) {
    clangArgs.push_back(each.c_str());
  }
  llvm::opt::InputArgList clangDriverArgs =
      parseClangDriverArgs(clangDriver, clangArgs);
  // If an SDK path was explicitly passed to Swift, make sure to pass it to
  // Clang driver as well. It affects the resulting include paths.
  auto sdkPath = ctx.SearchPathOpts.getSDKPath();
  if (!sdkPath.empty()) {
    unsigned argIndex = clangDriverArgs.MakeIndex("--sysroot", sdkPath);
    clangDriverArgs.append(new llvm::opt::Arg(
        clangDriver.getOpts().getOption(clang::driver::options::OPT__sysroot),
        sdkPath, argIndex));
  }
  return clangDriverArgs;
}

static bool shouldInjectGlibcModulemap(const llvm::Triple &triple) {
  return triple.isOSGlibc() || triple.isOSOpenBSD() || triple.isOSFreeBSD() ||
         triple.isAndroid();
}

static SmallVector<std::pair<std::string, std::string>, 2>
getGlibcFileMapping(ASTContext &ctx) {
  const llvm::Triple &triple = ctx.LangOpts.Target;
  if (!shouldInjectGlibcModulemap(triple))
    return {};

  // Extract the Glibc path from Clang driver.
  auto clangDriver = createClangDriver(ctx);
  auto clangDriverArgs = createClangArgs(ctx, clangDriver);

  llvm::opt::ArgStringList includeArgStrings;
  const auto &clangToolchain =
      clangDriver.getToolChain(clangDriverArgs, triple);
  clangToolchain.AddClangSystemIncludeArgs(clangDriverArgs, includeArgStrings);
  auto parsedIncludeArgs = parseClangDriverArgs(clangDriver, includeArgStrings);

  // Find the include path that contains Glibc headers. We use three arbitrarily
  // chosen headers to determine if the include path actually contains Glibc.
  // Ideally we would check that all of the headers referenced from the
  // modulemap are present.
  Path glibcDir;
  if (auto dir = findFirstIncludeDir(parsedIncludeArgs,
                                     {"inttypes.h", "unistd.h", "stdint.h"})) {
    glibcDir = dir.getValue();
  } else {
    ctx.Diags.diagnose(SourceLoc(), diag::glibc_not_found, triple.str());
    return {};
  }

  Path actualModuleMapPath;
  if (auto path = getGlibcModuleMapPath(ctx.SearchPathOpts, triple))
    actualModuleMapPath = path.getValue();
  else
    // FIXME: Emit a warning of some kind.
    return {};

  // Only inject the module map if it actually exists. It may not, for example
  // if `swiftc -target x86_64-unknown-linux-gnu -emit-ir` is invoked using
  // a Swift compiler not built for Linux targets.
  if (!llvm::sys::fs::exists(actualModuleMapPath))
    // FIXME: emit a warning of some kind.
    return {};

  // TODO: remove the SwiftGlibc.h header and reference all Glibc headers
  // directly from the modulemap.
  Path actualHeaderPath = actualModuleMapPath;
  llvm::sys::path::remove_filename(actualHeaderPath);
  llvm::sys::path::append(actualHeaderPath, "SwiftGlibc.h");

  Path injectedModuleMapPath(glibcDir);
  llvm::sys::path::append(injectedModuleMapPath, "module.modulemap");

  Path injectedHeaderPath(glibcDir);
  llvm::sys::path::append(injectedHeaderPath, "SwiftGlibc.h");

  return {
      {std::string(injectedModuleMapPath), std::string(actualModuleMapPath)},
      {std::string(injectedHeaderPath), std::string(actualHeaderPath)},
  };
}

static SmallVector<std::pair<std::string, std::string>, 2>
getLibStdCxxFileMapping(ASTContext &ctx) {
  assert(ctx.LangOpts.EnableCXXInterop &&
         "libstdc++ is only injected if C++ interop is enabled");

  const llvm::Triple &triple = ctx.LangOpts.Target;
  // We currently only need this when building for Linux.
  if (!triple.isOSLinux())
    return {};
  // Android uses libc++.
  if (triple.isAndroid())
    return {};

  // Extract the libstdc++ installation path from Clang driver.
  auto clangDriver = createClangDriver(ctx);
  auto clangDriverArgs = createClangArgs(ctx, clangDriver);

  llvm::opt::ArgStringList stdlibArgStrings;
  const auto &clangToolchain =
      clangDriver.getToolChain(clangDriverArgs, triple);
  clangToolchain.AddClangCXXStdlibIncludeArgs(clangDriverArgs,
                                              stdlibArgStrings);
  auto parsedStdlibArgs = parseClangDriverArgs(clangDriver, stdlibArgStrings);

  Path cxxStdlibDir;
  if (auto dir = findFirstIncludeDir(parsedStdlibArgs,
                                     {"cstdlib", "string", "vector"})) {
    cxxStdlibDir = dir.getValue();
  } else {
    ctx.Diags.diagnose(SourceLoc(), diag::libstdcxx_not_found, triple.str());
    return {};
  }

  Path actualModuleMapPath;
  if (auto path = getLibStdCxxModuleMapPath(ctx.SearchPathOpts, triple))
    actualModuleMapPath = path.getValue();
  else
    return {};

  // Only inject the module map if it actually exists. It may not, for example
  // if `swiftc -target x86_64-unknown-linux-gnu -emit-ir` is invoked using
  // a Swift compiler not built for Linux targets.
  if (!llvm::sys::fs::exists(actualModuleMapPath))
    // FIXME: emit a warning of some kind.
    return {};

  // TODO: remove the libstdcxx.h header and reference all libstdc++ headers
  // directly from the modulemap.
  Path actualHeaderPath = actualModuleMapPath;
  llvm::sys::path::remove_filename(actualHeaderPath);
  llvm::sys::path::append(actualHeaderPath, "libstdcxx.h");

  // Inject a modulemap into VFS for the libstdc++ directory.
  // Only inject the module map if the module does not already exist at
  // {sysroot}/usr/include/module.{map,modulemap}.
  Path injectedModuleMapPath;
  if (auto path = getInjectedModuleMapPath(cxxStdlibDir))
    injectedModuleMapPath = path.getValue();
  else
    return {};

  Path injectedHeaderPath(cxxStdlibDir);
  llvm::sys::path::append(injectedHeaderPath, "libstdcxx.h");

  return {
      {std::string(injectedModuleMapPath), std::string(actualModuleMapPath)},
      {std::string(injectedHeaderPath), std::string(actualHeaderPath)},
  };
}

SmallVector<std::pair<std::string, std::string>, 2>
swift::getClangInvocationFileMapping(ASTContext &ctx) {
  SmallVector<std::pair<std::string, std::string>, 2> result;

  result.append(getGlibcFileMapping(ctx));

  if (ctx.LangOpts.EnableCXXInterop) {
    result.append(getLibStdCxxFileMapping(ctx));
  }
  return result;
}
<commit_msg>[ClangImporter] Add the sysroot directly to the clang Driver used to find the libc header path<commit_after>//===--- ClangIncludePaths.cpp --------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "ClangIncludePaths.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsClangImporter.h"
#include "swift/Basic/Platform.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Frontend/CompilerInstance.h"

using namespace swift;

using Path = SmallString<128>;

static Optional<Path> getActualModuleMapPath(StringRef name,
                                             SearchPathOptions &Opts,
                                             const llvm::Triple &triple) {
  StringRef platform = swift::getPlatformNameForTriple(triple);
  StringRef arch = swift::getMajorArchitectureName(triple);

  Path result;

  StringRef SDKPath = Opts.getSDKPath();
  if (!SDKPath.empty()) {
    result.append(SDKPath.begin(), SDKPath.end());
    llvm::sys::path::append(result, "usr", "lib", "swift");
    llvm::sys::path::append(result, platform, arch, name);

    // Only specify the module map if that file actually exists.  It may not;
    // for example in the case that `swiftc -target x86_64-unknown-linux-gnu
    // -emit-ir` is invoked using a Swift compiler not built for Linux targets.
    if (llvm::sys::fs::exists(result))
      return result;
  }

  if (!Opts.RuntimeResourcePath.empty()) {
    result.clear();
    result.append(Opts.RuntimeResourcePath.begin(),
                  Opts.RuntimeResourcePath.end());
    llvm::sys::path::append(result, platform, arch, name);

    // Only specify the module map if that file actually exists.  It may not;
    // for example in the case that `swiftc -target x86_64-unknown-linux-gnu
    // -emit-ir` is invoked using a Swift compiler not built for Linux targets.
    if (llvm::sys::fs::exists(result))
      return result;
  }

  return None;
}

/// Given an include path directory, returns a path to inject the module map to.
/// If a module map already exists, returns `None`.
static llvm::Optional<Path> getInjectedModuleMapPath(const Path &dir) {
  Path legacyPath(dir);
  llvm::sys::path::append(legacyPath, "module.map");
  if (llvm::sys::fs::exists(legacyPath))
    return None;

  Path path(dir);
  llvm::sys::path::append(path, "module.modulemap");
  if (llvm::sys::fs::exists(path))
    return None;

  return path;
}

/// Finds the glibc.modulemap file relative to the provided resource dir.
///
/// Note that the module map used for Glibc depends on the target we're
/// compiling for, and is not included in the resource directory with the other
/// implicit module maps. It's at {freebsd|linux}/{arch}/glibc.modulemap.
static Optional<Path>
getGlibcModuleMapPath(SearchPathOptions &Opts, const llvm::Triple &triple) {
  return getActualModuleMapPath("glibc.modulemap", Opts, triple);
}

static Optional<Path>
getLibStdCxxModuleMapPath(SearchPathOptions &opts, const llvm::Triple &triple) {
  return getActualModuleMapPath("libstdcxx.modulemap", opts, triple);
}

Optional<SmallString<128>>
swift::getCxxShimModuleMapPath(SearchPathOptions &opts,
                               const llvm::Triple &triple) {
  return getActualModuleMapPath("libcxxshim.modulemap", opts, triple);
}

static llvm::opt::InputArgList
parseClangDriverArgs(const clang::driver::Driver &clangDriver,
                     const ArrayRef<const char *> args) {
  unsigned unused1, unused2;
  return clangDriver.getOpts().ParseArgs(args, unused1, unused2);
}

static clang::driver::Driver createClangDriver(const ASTContext &ctx) {
  auto clangDiags = clang::CompilerInstance::createDiagnostics(
      new clang::DiagnosticOptions());
  clang::driver::Driver clangDriver(ctx.ClangImporterOpts.clangPath,
                                    ctx.LangOpts.Target.str(), *clangDiags);
  return clangDriver;
}

/// Given a list of include paths and a list of file names, finds the first
/// include path that contains files with all the names. This is useful for
/// finding the include path for a specific library among a list of include
/// paths.
///
/// \return a path without dots (`../`, './').
static llvm::Optional<Path>
findFirstIncludeDir(const llvm::opt::InputArgList &args,
                    const ArrayRef<const char *> expectedFileNames) {
  // C++ stdlib paths are added as `-internal-isystem`.
  std::vector<std::string> includeDirs =
      args.getAllArgValues(clang::driver::options::OPT_internal_isystem);
  // C stdlib paths are added as `-internal-externc-isystem`.
  llvm::append_range(includeDirs,
                     args.getAllArgValues(
                         clang::driver::options::OPT_internal_externc_isystem));

  for (const auto &includeDir : includeDirs) {
    Path dir(includeDir);
    bool allExpectedExist = true;
    for (auto expectedFileName : expectedFileNames) {
      Path expectedFile(dir);
      llvm::sys::path::append(expectedFile, expectedFileName);
      if (!llvm::sys::fs::exists(expectedFile)) {
        allExpectedExist = false;
        break;
      }
    }

    if (allExpectedExist) {
      // VFS does not allow mapping paths that contain `../` or `./`.
      llvm::sys::path::remove_dots(dir, /*remove_dot_dot=*/true);
      return dir;
    }
  }
  return None;
}

static llvm::opt::InputArgList
createClangArgs(const ASTContext &ctx, clang::driver::Driver &clangDriver) {
  // Flags passed to Swift with `-Xcc` might affect include paths.
  std::vector<const char *> clangArgs;
  for (const auto &each : ctx.ClangImporterOpts.ExtraArgs) {
    clangArgs.push_back(each.c_str());
  }
  llvm::opt::InputArgList clangDriverArgs =
      parseClangDriverArgs(clangDriver, clangArgs);
  // If an SDK path was explicitly passed to Swift, make sure to pass it to
  // Clang driver as well. It affects the resulting include paths.
  auto sdkPath = ctx.SearchPathOpts.getSDKPath();
  if (!sdkPath.empty())
    clangDriver.SysRoot = sdkPath.str();
  return clangDriverArgs;
}

static bool shouldInjectGlibcModulemap(const llvm::Triple &triple) {
  return triple.isOSGlibc() || triple.isOSOpenBSD() || triple.isOSFreeBSD() ||
         triple.isAndroid();
}

static SmallVector<std::pair<std::string, std::string>, 2>
getGlibcFileMapping(ASTContext &ctx) {
  const llvm::Triple &triple = ctx.LangOpts.Target;
  if (!shouldInjectGlibcModulemap(triple))
    return {};

  // Extract the Glibc path from Clang driver.
  auto clangDriver = createClangDriver(ctx);
  auto clangDriverArgs = createClangArgs(ctx, clangDriver);

  llvm::opt::ArgStringList includeArgStrings;
  const auto &clangToolchain =
      clangDriver.getToolChain(clangDriverArgs, triple);
  clangToolchain.AddClangSystemIncludeArgs(clangDriverArgs, includeArgStrings);
  auto parsedIncludeArgs = parseClangDriverArgs(clangDriver, includeArgStrings);

  // Find the include path that contains Glibc headers. We use three arbitrarily
  // chosen headers to determine if the include path actually contains Glibc.
  // Ideally we would check that all of the headers referenced from the
  // modulemap are present.
  Path glibcDir;
  if (auto dir = findFirstIncludeDir(parsedIncludeArgs,
                                     {"inttypes.h", "unistd.h", "stdint.h"})) {
    glibcDir = dir.getValue();
  } else {
    ctx.Diags.diagnose(SourceLoc(), diag::glibc_not_found, triple.str());
    return {};
  }

  Path actualModuleMapPath;
  if (auto path = getGlibcModuleMapPath(ctx.SearchPathOpts, triple))
    actualModuleMapPath = path.getValue();
  else
    // FIXME: Emit a warning of some kind.
    return {};

  // TODO: remove the SwiftGlibc.h header and reference all Glibc headers
  // directly from the modulemap.
  Path actualHeaderPath = actualModuleMapPath;
  llvm::sys::path::remove_filename(actualHeaderPath);
  llvm::sys::path::append(actualHeaderPath, "SwiftGlibc.h");

  Path injectedModuleMapPath(glibcDir);
  llvm::sys::path::append(injectedModuleMapPath, "module.modulemap");

  Path injectedHeaderPath(glibcDir);
  llvm::sys::path::append(injectedHeaderPath, "SwiftGlibc.h");

  return {
      {std::string(injectedModuleMapPath), std::string(actualModuleMapPath)},
      {std::string(injectedHeaderPath), std::string(actualHeaderPath)},
  };
}

static SmallVector<std::pair<std::string, std::string>, 2>
getLibStdCxxFileMapping(ASTContext &ctx) {
  assert(ctx.LangOpts.EnableCXXInterop &&
         "libstdc++ is only injected if C++ interop is enabled");

  const llvm::Triple &triple = ctx.LangOpts.Target;
  // We currently only need this when building for Linux.
  if (!triple.isOSLinux())
    return {};
  // Android uses libc++.
  if (triple.isAndroid())
    return {};

  // Extract the libstdc++ installation path from Clang driver.
  auto clangDriver = createClangDriver(ctx);
  auto clangDriverArgs = createClangArgs(ctx, clangDriver);

  llvm::opt::ArgStringList stdlibArgStrings;
  const auto &clangToolchain =
      clangDriver.getToolChain(clangDriverArgs, triple);
  clangToolchain.AddClangCXXStdlibIncludeArgs(clangDriverArgs,
                                              stdlibArgStrings);
  auto parsedStdlibArgs = parseClangDriverArgs(clangDriver, stdlibArgStrings);

  Path cxxStdlibDir;
  if (auto dir = findFirstIncludeDir(parsedStdlibArgs,
                                     {"cstdlib", "string", "vector"})) {
    cxxStdlibDir = dir.getValue();
  } else {
    ctx.Diags.diagnose(SourceLoc(), diag::libstdcxx_not_found, triple.str());
    return {};
  }

  Path actualModuleMapPath;
  if (auto path = getLibStdCxxModuleMapPath(ctx.SearchPathOpts, triple))
    actualModuleMapPath = path.getValue();
  else
    return {};

  // Only inject the module map if it actually exists. It may not, for example
  // if `swiftc -target x86_64-unknown-linux-gnu -emit-ir` is invoked using
  // a Swift compiler not built for Linux targets.
  if (!llvm::sys::fs::exists(actualModuleMapPath))
    // FIXME: emit a warning of some kind.
    return {};

  // TODO: remove the libstdcxx.h header and reference all libstdc++ headers
  // directly from the modulemap.
  Path actualHeaderPath = actualModuleMapPath;
  llvm::sys::path::remove_filename(actualHeaderPath);
  llvm::sys::path::append(actualHeaderPath, "libstdcxx.h");

  // Inject a modulemap into VFS for the libstdc++ directory.
  // Only inject the module map if the module does not already exist at
  // {sysroot}/usr/include/module.{map,modulemap}.
  Path injectedModuleMapPath;
  if (auto path = getInjectedModuleMapPath(cxxStdlibDir))
    injectedModuleMapPath = path.getValue();
  else
    return {};

  Path injectedHeaderPath(cxxStdlibDir);
  llvm::sys::path::append(injectedHeaderPath, "libstdcxx.h");

  return {
      {std::string(injectedModuleMapPath), std::string(actualModuleMapPath)},
      {std::string(injectedHeaderPath), std::string(actualHeaderPath)},
  };
}

SmallVector<std::pair<std::string, std::string>, 2>
swift::getClangInvocationFileMapping(ASTContext &ctx) {
  SmallVector<std::pair<std::string, std::string>, 2> result;

  result.append(getGlibcFileMapping(ctx));

  if (ctx.LangOpts.EnableCXXInterop) {
    result.append(getLibStdCxxFileMapping(ctx));
  }
  return result;
}
<|endoftext|>