<commit_before>#include <errno.h>
#include <fcntl.h>
#include <iostream>
#include <linux/unistd.h>
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>

#include "library.h"
#include "maps.h"
#include "sandbox_impl.h"

namespace playground {

Maps::Maps(int proc_self_maps) :
    proc_self_maps_(proc_self_maps),
    begin_iter_(this, true, false),
    end_iter_(this, false, true),
    vsyscall_(0) {
  Sandbox::SysCalls sys;
  if (proc_self_maps_ >= 0 &&
      !sys.lseek(proc_self_maps_, 0, SEEK_SET)) {
    char buf[256] = { 0 };
    int len = 0, rc = 1;
    bool long_line = false;
    do {
      if (rc > 0) {
        rc = Sandbox::read(sys, proc_self_maps_, buf + len,
                           sizeof(buf) - len - 1);
        if (rc > 0) {
          len += rc;
        }
      }
      char *ptr = buf;
      if (!long_line) {
        long_line = true;
        unsigned long start = strtoul(ptr, &ptr, 16);
        unsigned long stop = strtoul(ptr + 1, &ptr, 16);
        while (*ptr == ' ' || *ptr == '\t') ++ptr;
        char *perm_ptr = ptr;
        while (*ptr && *ptr != ' ' && *ptr != '\t') ++ptr;
        std::string perm(perm_ptr, ptr - perm_ptr);
        unsigned long offset = strtoul(ptr, &ptr, 16);
        while (*ptr == ' ' || *ptr == '\t') ++ptr;
        char *id_ptr = ptr;
        while (*ptr && *ptr != ' ' && *ptr != '\t') ++ptr;
        while (*ptr == ' ' || *ptr == '\t') ++ptr;
        while (*ptr && *ptr != ' ' && *ptr != '\t') ++ptr;
        std::string id(id_ptr, ptr - id_ptr);
        while (*ptr == ' ' || *ptr == '\t') ++ptr;
        char *library_ptr = ptr;
        while (*ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '\n') ++ptr;
        std::string library(library_ptr, ptr - library_ptr);
        bool isVDSO = false;
        if (library == "[vdso]") {
          // /proc/self/maps has a misleading file offset in the [vdso] entry.
          // Override it with a sane value.
          offset = 0;
          isVDSO = true;
        } else if (library == "[vsyscall]") {
          vsyscall_ = reinterpret_cast<char *>(start);
        } else if (library.empty() || library[0] == '[') {
          goto skip_entry;
        }
        int prot = 0;
        if (perm.find('r') != std::string::npos) {
          prot |= PROT_READ;
        }
        if (perm.find('w') != std::string::npos) {
          prot |= PROT_WRITE;
        }
        if (perm.find('x') != std::string::npos) {
          prot |= PROT_EXEC;
        }
        if ((prot & (PROT_EXEC | PROT_READ)) == 0) {
          goto skip_entry;
        }
        Library* lib = &libs_[id + ' ' + library];
        lib->setLibraryInfo(this);
        lib->addMemoryRange(reinterpret_cast<void *>(start),
                            reinterpret_cast<void *>(stop),
                            Elf_Addr(offset),
                            prot, isVDSO);
      }
   skip_entry:
      for (;;) {
        if (!*ptr || *ptr++ == '\n') {
          long_line = false;
          memmove(buf, ptr, len - (ptr - buf));
          memset(buf + len - (ptr - buf), 0, ptr - buf);
          len -= (ptr - buf);
          break;
        }
      }
    } while (len || long_line);
  }
}

Maps::Iterator::Iterator(Maps* maps, bool at_beginning, bool at_end)
    : maps_(maps),
      at_beginning_(at_beginning),
      at_end_(at_end) {
}

Maps::LibraryMap::iterator& Maps::Iterator::getIterator() const {
  if (at_beginning_) {
    iter_ = maps_->libs_.begin();
  } else if (at_end_) {
    iter_ = maps_->libs_.end();
  }
  return iter_;
}

Maps::Iterator Maps::Iterator::begin() {
  return maps_->begin_iter_;
}

Maps::Iterator Maps::Iterator::end() {
  return maps_->end_iter_;
}

Maps::Iterator& Maps::Iterator::operator++() {
  getIterator().operator++();
  at_beginning_ = false;
  return *this;
}

Maps::Iterator Maps::Iterator::operator++(int i) {
  getIterator().operator++(i);
  at_beginning_ = false;
  return *this;
}

Library* Maps::Iterator::operator*() const {
  return &getIterator().operator*().second;
}

bool Maps::Iterator::operator==(const Maps::Iterator& iter) const {
  return getIterator().operator==(iter.getIterator());
}

bool Maps::Iterator::operator!=(const Maps::Iterator& iter) const {
  return !operator==(iter);
}

std::string Maps::Iterator::name() const {
  return getIterator()->first;
}

char* Maps::allocNearAddr(char* addr, size_t size, int prot) const {
  // We try to allocate memory within 1.5GB of a target address. This means,
  // we will be able to perform relative 32bit jumps from the target address.
  size = (size + 4095) & ~4095;
  Sandbox::SysCalls sys;
  if (sys.lseek(proc_self_maps_, 0, SEEK_SET)) {
    return NULL;
  }

  char buf[256] = { 0 };
  int len = 0, rc = 1;
  bool long_line = false;
  unsigned long gap_start = 0x10000;
  char *new_addr;
  do {
    if (rc > 0) {
      do {
        rc = Sandbox::read(sys, proc_self_maps_, buf + len,
                           sizeof(buf) - len - 1);
        if (rc > 0) {
          len += rc;
        }
      } while (rc > 0 && len < (int)sizeof(buf) - 1);
    }
    char *ptr = buf;
    if (!long_line) {
      long_line = true;
      unsigned long start = strtoul(ptr, &ptr, 16);
      unsigned long stop = strtoul(ptr + 1, &ptr, 16);
      if (start - gap_start >= size) {
        if (reinterpret_cast<long>(addr) - static_cast<long>(start) >= 0) {
          if (reinterpret_cast<long>(addr) - (start - size) < (1536 << 20)) {
            new_addr = reinterpret_cast<char *>(sys.MMAP
                           (reinterpret_cast<void *>(start - size), size, prot,
                            MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0));
            if (new_addr != MAP_FAILED) {
              goto done;
            }
          }
        } else if (gap_start + size - reinterpret_cast<long>(addr) <
                   (1536 << 20)) {
          new_addr = reinterpret_cast<char *>(sys.MMAP
                         (reinterpret_cast<void *>(gap_start), size, prot,
                          MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1 ,0));
          if (new_addr != MAP_FAILED) {
            goto done;
          }
        }
      }
      gap_start = stop;
    }
    for (;;) {
      if (!*ptr || *ptr++ == '\n') {
        long_line = false;
        memmove(buf, ptr, len - (ptr - buf));
        memset(buf + len - (ptr - buf), 0, ptr - buf);
        len -= (ptr - buf);
        break;
      }
    }
  } while (len || long_line);
  new_addr = NULL;
done:
  return new_addr;
}

} // namespace
<commit_msg>When finding scratch space for instrumenting the code, stay away from the main application stack, as it is usually mapped GROWS_DOWN and at the time when the sandbox starts, it might not yet have grown to its maximum size.<commit_after>#include <errno.h>
#include <fcntl.h>
#include <iostream>
#include <linux/unistd.h>
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>

#include "library.h"
#include "maps.h"
#include "sandbox_impl.h"

namespace playground {

Maps::Maps(int proc_self_maps) :
    proc_self_maps_(proc_self_maps),
    begin_iter_(this, true, false),
    end_iter_(this, false, true),
    vsyscall_(0) {
  Sandbox::SysCalls sys;
  if (proc_self_maps_ >= 0 &&
      !sys.lseek(proc_self_maps_, 0, SEEK_SET)) {
    char buf[256] = { 0 };
    int len = 0, rc = 1;
    bool long_line = false;
    do {
      if (rc > 0) {
        rc = Sandbox::read(sys, proc_self_maps_, buf + len,
                           sizeof(buf) - len - 1);
        if (rc > 0) {
          len += rc;
        }
      }
      char *ptr = buf;
      if (!long_line) {
        long_line = true;
        unsigned long start = strtoul(ptr, &ptr, 16);
        unsigned long stop = strtoul(ptr + 1, &ptr, 16);
        while (*ptr == ' ' || *ptr == '\t') ++ptr;
        char *perm_ptr = ptr;
        while (*ptr && *ptr != ' ' && *ptr != '\t') ++ptr;
        std::string perm(perm_ptr, ptr - perm_ptr);
        unsigned long offset = strtoul(ptr, &ptr, 16);
        while (*ptr == ' ' || *ptr == '\t') ++ptr;
        char *id_ptr = ptr;
        while (*ptr && *ptr != ' ' && *ptr != '\t') ++ptr;
        while (*ptr == ' ' || *ptr == '\t') ++ptr;
        while (*ptr && *ptr != ' ' && *ptr != '\t') ++ptr;
        std::string id(id_ptr, ptr - id_ptr);
        while (*ptr == ' ' || *ptr == '\t') ++ptr;
        char *library_ptr = ptr;
        while (*ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '\n') ++ptr;
        std::string library(library_ptr, ptr - library_ptr);
        bool isVDSO = false;
        if (library == "[vdso]") {
          // /proc/self/maps has a misleading file offset in the [vdso] entry.
          // Override it with a sane value.
          offset = 0;
          isVDSO = true;
        } else if (library == "[vsyscall]") {
          vsyscall_ = reinterpret_cast<char *>(start);
        } else if (library.empty() || library[0] == '[') {
          goto skip_entry;
        }
        int prot = 0;
        if (perm.find('r') != std::string::npos) {
          prot |= PROT_READ;
        }
        if (perm.find('w') != std::string::npos) {
          prot |= PROT_WRITE;
        }
        if (perm.find('x') != std::string::npos) {
          prot |= PROT_EXEC;
        }
        if ((prot & (PROT_EXEC | PROT_READ)) == 0) {
          goto skip_entry;
        }
        Library* lib = &libs_[id + ' ' + library];
        lib->setLibraryInfo(this);
        lib->addMemoryRange(reinterpret_cast<void *>(start),
                            reinterpret_cast<void *>(stop),
                            Elf_Addr(offset),
                            prot, isVDSO);
      }
   skip_entry:
      for (;;) {
        if (!*ptr || *ptr++ == '\n') {
          long_line = false;
          memmove(buf, ptr, len - (ptr - buf));
          memset(buf + len - (ptr - buf), 0, ptr - buf);
          len -= (ptr - buf);
          break;
        }
      }
    } while (len || long_line);
  }
}

Maps::Iterator::Iterator(Maps* maps, bool at_beginning, bool at_end)
    : maps_(maps),
      at_beginning_(at_beginning),
      at_end_(at_end) {
}

Maps::LibraryMap::iterator& Maps::Iterator::getIterator() const {
  if (at_beginning_) {
    iter_ = maps_->libs_.begin();
  } else if (at_end_) {
    iter_ = maps_->libs_.end();
  }
  return iter_;
}

Maps::Iterator Maps::Iterator::begin() {
  return maps_->begin_iter_;
}

Maps::Iterator Maps::Iterator::end() {
  return maps_->end_iter_;
}

Maps::Iterator& Maps::Iterator::operator++() {
  getIterator().operator++();
  at_beginning_ = false;
  return *this;
}

Maps::Iterator Maps::Iterator::operator++(int i) {
  getIterator().operator++(i);
  at_beginning_ = false;
  return *this;
}

Library* Maps::Iterator::operator*() const {
  return &getIterator().operator*().second;
}

bool Maps::Iterator::operator==(const Maps::Iterator& iter) const {
  return getIterator().operator==(iter.getIterator());
}

bool Maps::Iterator::operator!=(const Maps::Iterator& iter) const {
  return !operator==(iter);
}

std::string Maps::Iterator::name() const {
  return getIterator()->first;
}

// Test whether a line ends with "[stack]"; used for identifying the
// stack entry of /proc/self/maps.
static bool isStackLine(char* buf, char* end) {
  char* ptr = buf;
  for ( ; *ptr != '\n' && ptr < end; ++ptr)
    ;
  if (ptr < end && ptr - 7 > buf) {
    return (memcmp(ptr - 7, "[stack]", 7) == 0);
  }
  return false;
}

char* Maps::allocNearAddr(char* addr_target, size_t size, int prot) const {
  // We try to allocate memory within 1.5GB of a target address. This means,
  // we will be able to perform relative 32bit jumps from the target address.
  const unsigned long kMaxDistance = 1536 << 20;
  // In most of the code below, we just care about the numeric value of
  // the address.
  const long addr = reinterpret_cast<long>(addr_target);
  size = (size + 4095) & ~4095;
  Sandbox::SysCalls sys;
  if (sys.lseek(proc_self_maps_, 0, SEEK_SET)) {
    return NULL;
  }

  // Iterate through lines of /proc/self/maps to consider each mapped
  // region one at a time, looking for a gap between regions to allocate.
  char buf[256] = { 0 };
  int len = 0, rc = 1;
  bool long_line = false;
  unsigned long gap_start = 0x10000;
  void* new_addr;
  do {
    if (rc > 0) {
      do {
        rc = Sandbox::read(sys, proc_self_maps_, buf + len,
                           sizeof(buf) - len - 1);
        if (rc > 0) {
          len += rc;
        }
      } while (rc > 0 && len < (int)sizeof(buf) - 1);
    }
    char *ptr = buf;
    if (!long_line) {
      long_line = true;
      // Maps lines have the form "<start address>-<end address> ... <name>".
      unsigned long gap_end = strtoul(ptr, &ptr, 16);
      unsigned long map_end = strtoul(ptr + 1, &ptr, 16);

      // gap_start to gap_end now covers the region of empty space before
      // the current line.  Now we try to see if there's a place within the
      // gap we can use.

      if (gap_end - gap_start >= size) {
        // Is the gap before our target address?
        if (addr - static_cast<long>(gap_end) >= 0) {
          if (addr - (gap_end - size) < kMaxDistance) {
            unsigned long position;
            if (isStackLine(ptr, buf + len)) {
              // If we're adjacent to the stack, try to stay away from
              // the GROWS_DOWN region.  Pick the farthest away region that
              // is still within the gap.

              if (static_cast<unsigned long>(addr) < kMaxDistance ||  // Underflow protection.
                  static_cast<unsigned long>(addr) - kMaxDistance < gap_start) {
                position = gap_start;
              } else {
                position = addr - kMaxDistance;
              }
            } else {
              // Otherwise, take the end of the region.
              position = gap_end - size;
            }
            new_addr = reinterpret_cast<char *>(sys.MMAP
                           (reinterpret_cast<void *>(position), size, prot,
                            MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0));
            if (new_addr != MAP_FAILED) {
              goto done;
            }
          }
        } else if (gap_start + size - addr < kMaxDistance) {
          // Gap is after the address.  Above checks that we can wrap around
          // through 0 to a space we'd use.
          new_addr = reinterpret_cast<char *>(sys.MMAP
                         (reinterpret_cast<void *>(gap_start), size, prot,
                          MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1 ,0));
          if (new_addr != MAP_FAILED) {
            goto done;
          }
        }
      }
      gap_start = map_end;
    }
    for (;;) {
      if (!*ptr || *ptr++ == '\n') {
        long_line = false;
        memmove(buf, ptr, len - (ptr - buf));
        memset(buf + len - (ptr - buf), 0, ptr - buf);
        len -= (ptr - buf);
        break;
      }
    }
  } while (len || long_line);
  new_addr = NULL;
done:
  return reinterpret_cast<char*>(new_addr);
}

} // namespace
<|endoftext|>


<commit_before>#include <iostream>
#include <string.h>

int *array;
int COUNT;
int SIZE;

void printArray() {
	std::cout << "[";
	for(int i = 0; i < COUNT; i++) {
		std::cout << array[i];
		if(i < COUNT - 1) {
			std::cout << ", ";
		}
	}
	std::cout << "]" << std::endl;
}

void insertElement(int index, int element) {
	if(SIZE > COUNT) {
		memcpy(array, array, index * sizeof(int));
		memcpy(array + index + 1, array + index, (COUNT - index) * sizeof(int));
		array[index] = element;
		COUNT++;
	}
}

void appendElement(int element) {
	insertElement(COUNT, element);
}

void removeElement() {
	if(COUNT <= 0) {
		std::cout << "ERROR: Vector is empty" << std::endl;
		return;
	}
	COUNT--;
}

int main() {
	char option = '0';
	while(1) {
		switch(option) {
			case '0':
				std::cout << "Main Menu:\n\n1. Print the array\n"
				"2. Append element at the end\n"
				"3. Remove last element\n"
				"4. Insert one element\n"
				"5. Exit\n\n"
				"Select an option: ";

				std::cin >> option;
				break;

			case '1':  // Print the array
				std::cout << "You selected \"Print the array\"\n\n";
				option = '0';
				break;
			case '2':  // Append element at the end
				std::cout << "You selected \"Append element at the end\"\n\n";
				option = '0';
				break;
			case '3':  // Remove last element
				std::cout << "You selected \"Remove last element\"\n\n";
				option = '0';
				break;
			case '4':  // Insert one element
				std::cout << "You selected \"Insert one element\"\n\n";
				option = '0';
				break;
			case '5':  // Exit
				return 0;
			default:
				std::cout << "Invalid option " << option << '\n';
				option = '0';
				break;
		}
	}
}
<commit_msg>Write growArray method<commit_after>#include <iostream>
#include <string.h>

int *array;
int COUNT;
int SIZE;

void printArray() {
	std::cout << "[";
	for(int i = 0; i < COUNT; i++) {
		std::cout << array[i];
		if(i < COUNT - 1) {
			std::cout << ", ";
		}
	}
	std::cout << "] size = " << SIZE << std::endl;
}

void growArray() {
	SIZE *= 2;
	int *newarray = new int[SIZE];
	memcpy(newarray, array, COUNT * sizeof(int));
	array = newarray;
	std::cout << "Vector grown from " << SIZE / 2 << " to " << SIZE << std::endl;
}

void insertElement(int index, int element) {
	if(SIZE <= COUNT) {
		growArray();
	}
	memcpy(array, array, index * sizeof(int));
	memcpy(array + index + 1, array + index, (COUNT - index) * sizeof(int));
	array[index] = element;
	COUNT++;
}

void appendElement(int element) {
	insertElement(COUNT, element);
}

void removeElement() {
	if(COUNT <= 0) {
		std::cout << "ERROR: Vector is empty" << std::endl;
		return;
	}
	COUNT--;
}

int main() {
	char option = '0';
	while(1) {
		switch(option) {
			case '0':
				std::cout << "Main Menu:\n\n1. Print the array\n"
				"2. Append element at the end\n"
				"3. Remove last element\n"
				"4. Insert one element\n"
				"5. Exit\n\n"
				"Select an option: ";

				std::cin >> option;
				break;

			case '1':  // Print the array
				std::cout << "You selected \"Print the array\"\n\n";
				option = '0';
				break;
			case '2':  // Append element at the end
				std::cout << "You selected \"Append element at the end\"\n\n";
				option = '0';
				break;
			case '3':  // Remove last element
				std::cout << "You selected \"Remove last element\"\n\n";
				option = '0';
				break;
			case '4':  // Insert one element
				std::cout << "You selected \"Insert one element\"\n\n";
				option = '0';
				break;
			case '5':  // Exit
				return 0;
			default:
				std::cout << "Invalid option " << option << '\n';
				option = '0';
				break;
		}
	}
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

#define MAXN 100
#define MAXM 10000

struct edge{
	int u,v,w;

	bool operator < (edge e) const{
		return w < e.w;
	}
}e[MAXM];

bool in_tree[MAXM];

// Union - Find

int parent[MAXN + 1];

int Find(int x){
	if(parent[x] == x) return x;
	parent[x] = Find(parent[x]);
	return parent[x];
}

void Union(int x, int y){
	x = Find(x);
	y = Find(y);
	parent[x] = y;
}

// dfs to find a path between two nodes in the MST

vector<int> L[MAXN],edge_id[MAXN],path,path_edges;
bool visited[MAXN];

bool dfs(int u, int v){
	path.push_back(u);

	if(u == v) return true;

	bool ret = false;

	if(!visited[u]){
		visited[u] = true;

		for(int i = 0;i < L[u].size();++i){
			int to = L[u][i];
			path_edges.push_back(edge_id[u][i]);

			if(dfs(to,v)){
				ret = true;
				break;
			}else{
				path_edges.pop_back();
			}
		}
	}

	if(!ret)
		path.pop_back();

	return ret;
}

// dfs to mark edges in a subtree after erasing an edge

int mark[MAXN];

void dfs2(int u, int v, int cur){
	if(visited[cur]) return;
	visited[cur] = true;

	mark[cur] = u;

	for(int i = 0;i < L[cur].size();++i){
		int to = L[cur][i];

		if(to != u && to != v)
			dfs2(u,v,to);
	}
}

int main(){
	int n = 0,m = 0;

	while(scanf("%d,%d,%d",&e[m].u,&e[m].v,&e[m].w) == 3){
		n = max(n,max(e[m].u,e[m].v));
		++m;
	}

	// Find minimum spanning tree using Kruskal's algorithm

	for(int i = 1;i <= n;++i)
		parent[i] = i;

	sort(e,e + m);

	int total = 0;

	for(int i = 0;i < m;++i){
		if(Find(e[i].u) != Find(e[i].v)){
			Union(e[i].u,e[i].v);
			total += e[i].w;
			in_tree[i] = true;

			L[ e[i].u ].push_back(e[i].v);
			edge_id[ e[i].u ].push_back(i);

			L[ e[i].v ].push_back(e[i].u);
			edge_id[ e[i].v ].push_back(i);

			printf("%d - %d (%d)\n",e[i].u,e[i].v,e[i].w);
		}else in_tree[i] = false;
	}

	printf("Total weight = %d\n\n",total);

	// Find the path int T that connect two endpoint of an edge

	bool verified = true;

	for(int i = 0;i < m;++i){
		if(!in_tree[i]){
			memset(visited,false,sizeof visited);
			path.clear();
			dfs(e[i].u,e[i].v);

			printf("(%d, %d) : ",e[i].u,e[i].v);

			for(int j = 0;j < path.size();++j){
				if(j > 0) printf(" -> ");
				printf("%d",path[j]);
			}

			printf("\n");

			// Verify MST

			for(int j = 0;j < path_edges.size();++j){
				if(e[i].w < e[ path_edges[j] ].w)
					verified = false;
			}
		}
	}

	printf("\n");

	printf("Verification: ");
	if(verified) printf("It is an MST\n\n");
	else printf("It is not an MST\n\n");

	// Find edges that can replace an edge in the MST

	int most_vital_edge = -1;
	int min_increase = -1;

	for(int i = 0;i < m;++i){
		if(in_tree[i]){
			memset(visited,false,sizeof visited);
			dfs2(e[i].u,e[i].v,e[i].u);
			dfs2(e[i].v,e[i].u,e[i].v);

			printf("(%d, %d) :",e[i].u,e[i].v);

			int rep = -1;

			for(int j = 0;j < m;++j)
				if(j != i && ((mark[ e[j].u ] == e[i].u && mark[ e[j].v ] == e[i].v) || (mark[ e[j].v ] == e[i].u && mark[ e[j].u ] == e[i].v))){
					printf(" (%d, %d)",e[j].u,e[j].v);

					if(rep == -1 || e[j].w < e[rep].w)
						rep = j;
				}

			printf(", replacement : (%d, %d)\n",e[rep].u,e[rep].v);

			if(most_vital_edge == -1 || e[rep].w - e[i].w < min_increase){
				min_increase = e[rep].w - e[i].w;
				most_vital_edge = i;
			}

			/*
			//test

			for(int j = 1;j <= n;++j)
				parent[j] = j;

			for(int j = 0;j < m;++j){
				if(j != i && Find(e[j].u) != Find(e[j].v)){
					Union(e[j].u,e[j].v);
					if(!in_tree[j])
						printf("(%d, %d)\n",e[j].u,e[j].v);
				}
			}*/
		}
	}

	printf("\n");
	printf("Most vital edge = (%d, %d)\n",e[most_vital_edge].u,e[most_vital_edge].v);
	printf("Increase = %d\n",min_increase);

	return 0;
}<commit_msg>sensitivity for tree edges<commit_after>#include <cstdio>
#include <cstring>
#include <climits>
#include <algorithm>
#include <vector>

using namespace std;

#define MAXN 100
#define MAXM 10000

int n,m;

struct edge{
	int u,v,w;

	bool operator < (edge e) const{
		return w < e.w;
	}
}e[MAXM];

bool in_tree[MAXM];

// Union - Find

int parent[MAXN + 1];

int Find(int x){
	if(parent[x] == x) return x;
	parent[x] = Find(parent[x]);
	return parent[x];
}

void Union(int x, int y){
	x = Find(x);
	y = Find(y);
	parent[x] = y;
}

// dfs to find a path between two nodes in the MST

vector<int> L[MAXN],edge_id[MAXN],path,path_edges;
bool visited[MAXN];

bool dfs(int u, int v){
	path.push_back(u);

	if(u == v) return true;

	bool ret = false;

	if(!visited[u]){
		visited[u] = true;

		for(int i = 0;i < L[u].size();++i){
			int to = L[u][i];
			path_edges.push_back(edge_id[u][i]);

			if(dfs(to,v)){
				ret = true;
				break;
			}else{
				path_edges.pop_back();
			}
		}
	}

	if(!ret)
		path.pop_back();

	return ret;
}

// dfs to mark edges in a subtree after erasing an edge

int mark[MAXN];

void dfs2(int u, int v, int cur){
	if(visited[cur]) return;
	visited[cur] = true;

	mark[cur] = u;

	for(int i = 0;i < L[cur].size();++i){
		int to = L[cur][i];

		if(to != u && to != v)
			dfs2(u,v,to);
	}
}

// dfs to root the tree
int a[MAXN],in[MAXN],out[MAXN],cont;
int parent_lca[10][MAXN];
int height[MAXN];

void dfs3(int cur, int p = 0){
	a[cont] = cur;
	in[cur] = cont++;

	parent_lca[0][cur] = p;
	height[cur] = (p == 0? 0 : 1 + height[p]);

	for(int i = 1;i <= 9;++i)
		parent_lca[i][cur] = parent_lca[i - 1][ parent_lca[i - 1][cur] ];

	for(int i = (int)L[cur].size() - 1;i >= 0;--i){
		int to = L[cur][i];

		if(to != p)
			dfs3(to,cur);
	}

	out[cur] = cont;
}

// lowest common ancestor

int lca(int u, int v){
	if(height[u] < height[v])
		swap(u,v);

	for(int i = 9;i >= 0;--i)
		if((height[u] - height[v]) >> i & 1)
			u = parent_lca[i][u];

	if(u == v)
		return u;

	for(int i = 9;i >= 0;--i)
		if(parent_lca[i][u] != parent_lca[i][v]){
			u = parent_lca[i][u];
			v = parent_lca[i][v];
		}

	return parent_lca[0][u];
}

// dfs for the sensitivity analysis of tree edges

int k[MAXN],tree_sensitivity[MAXN];

void dfs4(int cur, int p){
	if(p != 0)
		tree_sensitivity[cur] = query(0,0,n - 1,in[cur],out[cur]);

	// update?

	for(int i = (int)L[cur].size() - 1;i >= 0;--i){
		int to = L[cur][i];

		if(to != p)
			dfs4(to,cur);
	}
}

int main(){
	n = m = 0;

	while(scanf("%d,%d,%d",&e[m].u,&e[m].v,&e[m].w) == 3){
		n = max(n,max(e[m].u,e[m].v));
		++m;
	}

	// Find minimum spanning tree using Kruskal's algorithm

	for(int i = 1;i <= n;++i)
		parent[i] = i;

	sort(e,e + m);

	int total = 0;

	for(int i = 0;i < m;++i){
		if(Find(e[i].u) != Find(e[i].v)){
			Union(e[i].u,e[i].v);
			total += e[i].w;
			in_tree[i] = true;

			L[ e[i].u ].push_back(e[i].v);
			edge_id[ e[i].u ].push_back(i);

			L[ e[i].v ].push_back(e[i].u);
			edge_id[ e[i].v ].push_back(i);

			printf("%d - %d (%d)\n",e[i].u,e[i].v,e[i].w);
		}else in_tree[i] = false;
	}

	printf("Total weight = %d\n\n",total);

	// Find the path int T that connect two endpoint of an edge

	bool verified = true;

	for(int i = 0;i < m;++i){
		if(!in_tree[i]){
			memset(visited,false,sizeof visited);
			path.clear();
			dfs(e[i].u,e[i].v);

			printf("(%d, %d) : ",e[i].u,e[i].v);

			for(int j = 0;j < path.size();++j){
				if(j > 0) printf(" -> ");
				printf("%d",path[j]);
			}

			printf("\n");

			// Verify MST

			for(int j = 0;j < path_edges.size();++j){
				if(e[i].w < e[ path_edges[j] ].w)
					verified = false;
			}
		}
	}

	printf("\n");

	printf("Verification: ");
	if(verified) printf("It is an MST\n\n");
	else printf("It is not an MST\n\n");

	// Find edges that can replace an edge in the MST

	int most_vital_edge = -1;
	int min_increase = -1;

	for(int i = 0;i < m;++i){
		if(in_tree[i]){
			memset(visited,false,sizeof visited);
			dfs2(e[i].u,e[i].v,e[i].u);
			dfs2(e[i].v,e[i].u,e[i].v);

			printf("(%d, %d) :",e[i].u,e[i].v);

			int rep = -1;

			for(int j = 0;j < m;++j)
				if(j != i && ((mark[ e[j].u ] == e[i].u && mark[ e[j].v ] == e[i].v) || (mark[ e[j].v ] == e[i].u && mark[ e[j].u ] == e[i].v))){
					printf(" (%d, %d)",e[j].u,e[j].v);

					if(rep == -1 || e[j].w < e[rep].w)
						rep = j;
				}

			printf(", replacement : (%d, %d)\n",e[rep].u,e[rep].v);

			if(most_vital_edge == -1 || e[rep].w - e[i].w < min_increase){
				min_increase = e[rep].w - e[i].w;
				most_vital_edge = i;
			}

			/*
			//test

			for(int j = 1;j <= n;++j)
				parent[j] = j;

			for(int j = 0;j < m;++j){
				if(j != i && Find(e[j].u) != Find(e[j].v)){
					Union(e[j].u,e[j].v);
					if(!in_tree[j])
						printf("(%d, %d)\n",e[j].u,e[j].v);
				}
			}*/
		}
	}

	printf("\n");
	printf("Most vital edge = (%d, %d)\n",e[most_vital_edge].u,e[most_vital_edge].v);
	printf("Increase = %d\n",min_increase);

	// Sensitivity analysis for tree edges

	cont = 0;
	dfs3(1,0);

	for(int i = 1;i <= n;++i)
		k[i] = INT_MAX;

	dfs4(1,0);

	return 0;
}<|endoftext|>


<commit_before>/*
** This is free and unencumbered software released into the public domain.
**
** Anyone is free to copy, modify, publish, use, compile, sell, or
** distribute this software, either in source code form or as a compiled
** binary, for any purpose, commercial or non-commercial, and by any
** means.
**
** In jurisdictions that recognize copyright laws, the author or authors
** of this software dedicate any and all copyright interest in the
** software to the public domain. We make this dedication for the benefit
** of the public at large and to the detriment of our heirs and
** successors. We intend this dedication to be an overt act of
** relinquishment in perpetuity of all present and future rights to this
** software under copyright law.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
** OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
** OTHER DEALINGS IN THE SOFTWARE.
**
** For more information, please refer to <http://unlicense.org/>
*/

#ifndef VXL_ONB_HPP
# define VXL_ONB_HPP
# pragma once

#include "vector.hpp"

namespace vxl
{

// Graphics Tools---The jgt Editors' Choice
// Building an orthonormal basis from a unit vector
// Building an Orthonormal Basis from a 3D Unit Vector Without Normalization
// http://blog.selfshadow.com/2011/10/17/perp-vectors/
// http://lolengine.net/blog/2013/09/21/picking-orthogonal-vector-combing-coconuts
//////////////////////////////////////////////////////////////////////////////
template <typename T>
//__attribute__ ((noinline))
constexpr inline vector<T, 2> cortho(vector<T, 2> const& v,
  default_tag const = {}) noexcept
{
  return vector<T, 2>{-v(1), v(0)};
}

//////////////////////////////////////////////////////////////////////////////
template <typename T>
//__attribute__ ((noinline))
constexpr inline vector<T, 3> cortho(vector<T, 3> const& v,
  default_tag const = {}) noexcept
{
  using int_value_type = typename vector_traits<float, 3>::int_value_type;
  using vector_type = typename vector_traits<float, 3>::vector_type;

  auto const tmp(cabs(v));

/*
  return tmp(0) < tmp(1) ?
    vector<T, 3>{T(0), -v(2), v(1)} :
    vector<T, 3>{-v(1), v(0), T(0)};
*/

  // if abs(x) < abs(y), then the largest components are either y or z
  return {
    select(
      vector_type{T(0), -v(2), v(1)},
      vector_type{-v(1), v(0), T(0)},
      cvector<int_value_type, 3>(-(tmp(0) < tmp(1)))
    )
  };
}

}

#endif // VXL_ONB_HPP
<commit_msg>some fixes<commit_after>/*
** This is free and unencumbered software released into the public domain.
**
** Anyone is free to copy, modify, publish, use, compile, sell, or
** distribute this software, either in source code form or as a compiled
** binary, for any purpose, commercial or non-commercial, and by any
** means.
**
** In jurisdictions that recognize copyright laws, the author or authors
** of this software dedicate any and all copyright interest in the
** software to the public domain. We make this dedication for the benefit
** of the public at large and to the detriment of our heirs and
** successors. We intend this dedication to be an overt act of
** relinquishment in perpetuity of all present and future rights to this
** software under copyright law.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
** OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
** OTHER DEALINGS IN THE SOFTWARE.
**
** For more information, please refer to <http://unlicense.org/>
*/

#ifndef VXL_ONB_HPP
# define VXL_ONB_HPP
# pragma once

#include "vector.hpp"

namespace vxl
{

// Graphics Tools---The jgt Editors' Choice
// Building an orthonormal basis from a unit vector
// Building an Orthonormal Basis from a 3D Unit Vector Without Normalization
// http://blog.selfshadow.com/2011/10/17/perp-vectors/
// http://lolengine.net/blog/2013/09/21/picking-orthogonal-vector-combing-coconuts
//////////////////////////////////////////////////////////////////////////////
template <typename T>
//__attribute__ ((noinline))
constexpr inline vector<T, 2> cortho(vector<T, 2> const& v,
  default_tag const = {}) noexcept
{
  return {-v(1), v(0)};
}

//////////////////////////////////////////////////////////////////////////////
template <typename T>
//__attribute__ ((noinline))
constexpr inline vector<T, 3> cortho(vector<T, 3> const& v,
  default_tag const = {}) noexcept
{
  using int_value_type = typename vector_traits<float, 3>::int_value_type;
  using vector_type = typename vector_traits<float, 3>::vector_type;

  auto const tmp(cabs(v));

/*
  return tmp(0) < tmp(1) ?
    vector<T, 3>{T(0), -v(2), v(1)} :
    vector<T, 3>{-v(1), v(0), T(0)};
*/

  // if abs(x) < abs(y), then the largest components are either y or z
  return {
    select(
      vector_type{T(0), -v(2), v(1)},
      vector_type{-v(1), v(0), T(0)},
      cvector<int_value_type, 3>(-(tmp(0) < tmp(1)))
    )
  };
}

}

#endif // VXL_ONB_HPP
<|endoftext|>


<commit_before>/**
 * Steps to do for pwm
 * 1. "echo am33xx_pwm > /sys/devices/bone_capemgr.9/slots"
 * 2. "echo bone_pwm_P8_13 > /sys/devices/bone_capemgr.9/slots"
 * 3. "cd /sys/devices/ocp.3/pwm_test_P8_13.16/"
 * 4. "echo 0 > duty" for max value or "echo 500000 > duty" for min value
 */

#include "gpio.hpp"

#include <cassert>
#include <glob.h>
#include <sstream>

using namespace std;

GPIO::GPIO() :
	PWM_PERIOD(50000) // nanoseconds = 2000 Hz
{
	// Enable the pwm pins
	echo("/sys/devices/bone_capemgr.9/slots", "am33xx_pwm");

	// Prepare P8_13
	echo("/sys/devices/bone_capemgr.9/slots", "bone_pwm_P8_13");
	cout << "Finding PWM pin paths:\n";
	string path = matchPath("/sys/devices/ocp.*/pwm_test_P8_13.*/");
	cout << path << endl;

	echo("/sys/devices/bone_capemgr.9/slots", "bone_pwm_P8_19");
	echo("/sys/devices/bone_capemgr.9/slots", "bone_pwm_P9_14");
	echo("/sys/devices/bone_capemgr.9/slots", "bone_pwm_P9_16");

	// Do not change the order of pins here. The PIN enum is used to access
	// these paths, so their order is important.
	_pwmPinPaths.push_back(path);
	path = matchPath("/sys/devices/ocp.*/pwm_test_P8_19.*/");
	cout << path << endl;
	_pwmPinPaths.push_back(path);
	path = matchPath("/sys/devices/ocp.*/pwm_test_P9_14.*/");
	cout << path << endl;
	_pwmPinPaths.push_back(path);
	path = matchPath("/sys/devices/ocp.*/pwm_test_P9_16.*/");
	cout << path << endl;
	_pwmPinPaths.push_back(path);

	// Set PWM period for both outputs
	int result = echo(append(_pwmPinPaths[P8_13], "period"), PWM_PERIOD);
	if(result != 0) {
		cout << "At least one echo failed\n";
	}
	result = echo(append(_pwmPinPaths[P8_19], "period"), PWM_PERIOD);
	if(result != 0) {
		cout << "At least one echo failed\n";
	}
	result = echo(append(_pwmPinPaths[P9_14], "period"), PWM_PERIOD);
	if(result != 0) {
		cout << "At least one echo failed\n";
	}
	result = echo(append(_pwmPinPaths[P9_16], "period"), PWM_PERIOD);
	if(result != 0) {
		cout << "At least one echo failed\n";
	}
}

GPIO::~GPIO()
{

}

void GPIO::setPin(const Pin pin, const bool value)
{
	assert(value == 0 || value == 1);

	// already exported?
	if (!containsPin(pin)) {
		exportPin(pin);
	}

	stringstream ss;
	ss << "/sys/class/gpio/gpio" << pin << "/value";
	string pinPath = ss.str();
	echo(pinPath, value);
}

/* Duty cycle in percent */
void GPIO::setPwm(const PwmPin pin, const float dutyPerc)
{
	/*
	https://groups.google.com/forum/#!topic/beagleboard/qma8bMph0yM

	This will connect PWM to pin P9_14 and generate on the pin  ~2MHz
	waveform with 50% duty.

	modprobe pwm_test
	echo am33xx_pwm > /sys/devices/bone_capemgr.9/slots
	echo bone_pwm_P9_14 > /sys/devices/bone_capemgr.9/slots
	echo 500 > /sys/devices/ocp.2/pwm_test_P9_14.16/period
	echo 250 > /sys/devices/ocp.2/pwm_test_P9_14.16/duty
	*/

	assert(dutyPerc >= 0.0);
	assert(dutyPerc <= 1.0);

	// The beaglebone interprets duty == period as 0 V output and duty == 0 results in
	// 3.3 V output, so we invert the value here to make 0 % duty correspond to 0 V output.
	const int duty = (1.0 - dutyPerc) * 500000;
	int result = 0;
	result = echo(append(_pwmPinPaths[pin], "duty"), duty);

	if(result != 0) {
		cout << "At least one echo failed\n";
	}
}

bool GPIO::containsPin(const Pin pin)
{
	for (vector<int>::iterator it = _exportedPins.begin();
			it != _exportedPins.end(); it++) {
		if (*it == pin) {
			return true;
		}
	}

	return false;
}

void GPIO::exportPin(const Pin pin)
{
	// Construct the base path to the pin
	stringstream ss;
  	ss << "/sys/class/gpio/gpio" << pin << "/";
  	string basePath = ss.str();

  	echo("/sys/class/gpio/export", pin);
  	echo(append(basePath, "direction"), "out");

// WTF?

	/*strcpy(setValue, GPIOString);
	if(fwrite(&setValue, sizeof(char), 2, outputHandle) == -1)
		cerr << "kaputt\n";
	fclose(outputHandle);*/

	_exportedPins.push_back(pin);
}

int GPIO::echo(const string target, const int value)
{
	ofstream file(target.c_str());
	if(!file) {
		cerr << "Could not open " << target << endl;
		return -1;
	}

	file << value;
	file.close();
	return 0;
}

int GPIO::echo(const string target, const char *value)
{
	ofstream file(target.c_str());
	if(!file) {
		cerr << "Could not open " << target << endl;
		return -1;
	}

	file << value;
	file.close();
	return 0;
}

string GPIO::matchPath(const std::string pattern)
{

	// Find the pwm pin paths (they change on every reboot...)
	// int glob(const char *pattern, int flags,
	//			int (*errfunc) (const char *epath, int eerrno),
	//			glob_t *pglob);
	glob_t foundPaths;
	int result = glob(pattern.c_str(), GLOB_ERR | GLOB_MARK, NULL, &foundPaths);

	switch(result) {
	case 0:
		if(foundPaths.gl_pathc != 1) {
			cout << "Warning: PWM pin path pattern (tm) matched more than one path. Taking the first one.\n";
		}
		return string(foundPaths.gl_pathv[0]);
	case GLOB_NOSPACE:
		cerr << "Call to glob ran out of memory!\n";
		break;
	case GLOB_ABORTED:
		cerr << "Glob encountered a read error (are we root?)\n";
		break;
	case GLOB_NOMATCH:
		cerr << "Glob couldn't match a path\n";
		break;
	default:
		cerr << "Unexpected glob error!\n";
	}

	return string();
}
<commit_msg>Reorder pwm pin initialization<commit_after>/**
 * Steps to do for pwm
 * 1. "echo am33xx_pwm > /sys/devices/bone_capemgr.9/slots"
 * 2. "echo bone_pwm_P8_13 > /sys/devices/bone_capemgr.9/slots"
 * 3. "cd /sys/devices/ocp.3/pwm_test_P8_13.16/"
 * 4. "echo 0 > duty" for max value or "echo 500000 > duty" for min value
 */

#include "gpio.hpp"

#include <cassert>
#include <glob.h>
#include <sstream>

using namespace std;

GPIO::GPIO() :
	PWM_PERIOD(50000) // nanoseconds = 2000 Hz
{
	// Enable the pwm pins
	echo("/sys/devices/bone_capemgr.9/slots", "am33xx_pwm");

	// Do not change the order of pins here. The PIN enum is used to access
	// these paths, so their order is important.
	cout << "Finding PWM pin paths:\n";
	echo("/sys/devices/bone_capemgr.9/slots", "bone_pwm_P8_13");
	string path = matchPath("/sys/devices/ocp.*/pwm_test_P8_13.*/");
	cout << path << endl;
	_pwmPinPaths.push_back(path);
	echo("/sys/devices/bone_capemgr.9/slots", "bone_pwm_P8_19");
	path = matchPath("/sys/devices/ocp.*/pwm_test_P8_19.*/");
	cout << path << endl;
	_pwmPinPaths.push_back(path);
	echo("/sys/devices/bone_capemgr.9/slots", "bone_pwm_P9_14");
	path = matchPath("/sys/devices/ocp.*/pwm_test_P9_14.*/");
	cout << path << endl;
	_pwmPinPaths.push_back(path);
	echo("/sys/devices/bone_capemgr.9/slots", "bone_pwm_P9_16");
	path = matchPath("/sys/devices/ocp.*/pwm_test_P9_16.*/");
	cout << path << endl;
	_pwmPinPaths.push_back(path);

	// Set PWM period for both outputs
	int result = echo(append(_pwmPinPaths[P8_13], "period"), PWM_PERIOD);
	if(result != 0) {
		cout << "At least one echo failed\n";
	}
	result = echo(append(_pwmPinPaths[P8_19], "period"), PWM_PERIOD);
	if(result != 0) {
		cout << "At least one echo failed\n";
	}
	result = echo(append(_pwmPinPaths[P9_14], "period"), PWM_PERIOD);
	if(result != 0) {
		cout << "At least one echo failed\n";
	}
	result = echo(append(_pwmPinPaths[P9_16], "period"), PWM_PERIOD);
	if(result != 0) {
		cout << "At least one echo failed\n";
	}
}

GPIO::~GPIO()
{

}

void GPIO::setPin(const Pin pin, const bool value)
{
	assert(value == 0 || value == 1);

	// already exported?
	if (!containsPin(pin)) {
		exportPin(pin);
	}

	stringstream ss;
	ss << "/sys/class/gpio/gpio" << pin << "/value";
	string pinPath = ss.str();
	echo(pinPath, value);
}

/* Duty cycle in percent */
void GPIO::setPwm(const PwmPin pin, const float dutyPerc)
{
	/*
	https://groups.google.com/forum/#!topic/beagleboard/qma8bMph0yM

	This will connect PWM to pin P9_14 and generate on the pin  ~2MHz
	waveform with 50% duty.

	modprobe pwm_test
	echo am33xx_pwm > /sys/devices/bone_capemgr.9/slots
	echo bone_pwm_P9_14 > /sys/devices/bone_capemgr.9/slots
	echo 500 > /sys/devices/ocp.2/pwm_test_P9_14.16/period
	echo 250 > /sys/devices/ocp.2/pwm_test_P9_14.16/duty
	*/

	assert(dutyPerc >= 0.0);
	assert(dutyPerc <= 1.0);

	// The beaglebone interprets duty == period as 0 V output and duty == 0 results in
	// 3.3 V output, so we invert the value here to make 0 % duty correspond to 0 V output.
	const int duty = (1.0 - dutyPerc) * 500000;
	int result = 0;
	result = echo(append(_pwmPinPaths[pin], "duty"), duty);

	if(result != 0) {
		cout << "At least one echo failed\n";
	}
}

bool GPIO::containsPin(const Pin pin)
{
	for (vector<int>::iterator it = _exportedPins.begin();
			it != _exportedPins.end(); it++) {
		if (*it == pin) {
			return true;
		}
	}

	return false;
}

void GPIO::exportPin(const Pin pin)
{
	// Construct the base path to the pin
	stringstream ss;
  	ss << "/sys/class/gpio/gpio" << pin << "/";
  	string basePath = ss.str();

  	echo("/sys/class/gpio/export", pin);
  	echo(append(basePath, "direction"), "out");

// WTF?

	/*strcpy(setValue, GPIOString);
	if(fwrite(&setValue, sizeof(char), 2, outputHandle) == -1)
		cerr << "kaputt\n";
	fclose(outputHandle);*/

	_exportedPins.push_back(pin);
}

int GPIO::echo(const string target, const int value)
{
	ofstream file(target.c_str());
	if(!file) {
		cerr << "Could not open " << target << endl;
		return -1;
	}

	file << value;
	file.close();
	return 0;
}

int GPIO::echo(const string target, const char *value)
{
	ofstream file(target.c_str());
	if(!file) {
		cerr << "Could not open " << target << endl;
		return -1;
	}

	file << value;
	file.close();
	return 0;
}

string GPIO::matchPath(const std::string pattern)
{

	// Find the pwm pin paths (they change on every reboot...)
	// int glob(const char *pattern, int flags,
	//			int (*errfunc) (const char *epath, int eerrno),
	//			glob_t *pglob);
	glob_t foundPaths;
	int result = glob(pattern.c_str(), GLOB_ERR | GLOB_MARK, NULL, &foundPaths);

	switch(result) {
	case 0:
		if(foundPaths.gl_pathc != 1) {
			cout << "Warning: PWM pin path pattern (tm) matched more than one path. Taking the first one.\n";
		}
		return string(foundPaths.gl_pathv[0]);
	case GLOB_NOSPACE:
		cerr << "Call to glob ran out of memory!\n";
		break;
	case GLOB_ABORTED:
		cerr << "Glob encountered a read error (are we root?)\n";
		break;
	case GLOB_NOMATCH:
		cerr << "Glob couldn't match a path\n";
		break;
	default:
		cerr << "Unexpected glob error!\n";
	}

	return string();
}
<|endoftext|>


<commit_before>/* The MIT License (MIT)
 *
 * Copyright (c) 2015 Giovanni Ortolani, Taneli Mikkonen, Pingjiang Li, Tommi Puolamaa, Mitra Vahida
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE. */

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "freqampdialog.h"
#include "../ResourceParameter.h"
#include <QDebug>
#include <QColorDialog>
#include <QVectorIterator>
#include <QtMath>
#include <QFileDialog>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    setFixedSize(geometry().width(), geometry().height());

    //Regex validators to handle 2 decimal float values from 0-100
    QRegExp rex("[0-9][0-9]\\.\\d{0,2}|[0-9]\\.\\d{0,2}|(100)");
    QRegExpValidator *radiusvalidator = new QRegExpValidator(rex, this);

    ui->lineEdit->setValidator( radiusvalidator );

    QRegExp rex2("[0-9][0-9]\\.\\d{0,2}|[0-9]\\.\\d{0,2}|(100)");
    QRegExpValidator *watervalidator = new QRegExpValidator(rex2, this);

    ui->lineEdit_2->setValidator( watervalidator );

    //regex to handle max value for lineEdit to be 2*32-1 (UINT_MAX)
    QRegExp rx("^(\\d|\\d{1,9}|[0-3]\\d{1,9}|4[0-1]\\d{8}|42[0-8]\\d{7}|429[0-3]\\d{6}|4294[0-8]\\d{5}|42949[0-5]\\d{4}|429496[0-6]\\d{3}|4294967[0-1]\\d{2}|429496729[0-5])$");
    QValidator *validator = new QRegExpValidator(rx, this);
    ui->lineEdit_3->setValidator(validator);

	//set default parameters for now::
	/*vector<float> frequency;
	frequency.push_back(0.4);
	frequency.push_back(0.06666);
	vector <float> amplitude;
	amplitude.push_back(0.02);
	amplitude.push_back(0.006666);*/

	std::string frequencyAmplitude = "1.0 0.02 0.3 0.008 0.1 0.005 0.06666 0.006666";
    std::vector < std::pair < std::string, int > > meshlocs;
    meshlocs.push_back(std::make_pair("media/models/ram.mesh", 1));
    meshlocs.push_back(std::make_pair("media/models/asteroid.mesh", 1));

	float waterfraction = 0.6;
	float radius = 7.5;
    int seed = 60;

    ui->lineEdit->setText(""+QString::number(radius));
    ui->lineEdit_2->setText(""+QString::number(waterfraction*100));
    ui->lineEdit_3->setText(""+QString::number(seed));

    params = new std::ResourceParameter((std::string)"#00FF00",(std::string)"#FACD00",(std::string)"#32CDFF"
        ,(std::string)"#64FFFF",(std::string)"#B4B4B4",(std::string)"#FFFFFF",waterfraction,radius,seed,frequencyAmplitude, meshlocs);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
	if(!ui->lineEdit->text().isEmpty())
    {
        float radius = ui->lineEdit->text().toFloat();
        params->setRadius(radius);
    }

    if(!ui->lineEdit_2->text().isEmpty())
    {
        float waterfraction = (ui->lineEdit_2->text().toFloat())/100;
        params->setWaterFraction(waterfraction);
    }
    if(!ui->lineEdit_3->text().isEmpty())
    {
        int seed = ui->lineEdit_3->text().toInt();
        params->setSeed(seed);
    }

    if(ui->pushButton_2->text() != "Color")
    {
        params->setWaterFirstColor(ui->pushButton_2->text().toUtf8().constData());
    }
    if(ui->pushButton_3->text() != "Color")
    {
        params->setWaterSecondColor(ui->pushButton_3->text().toUtf8().constData());
    }

    if(ui->pushButton_4->text() != "Color")
    {
        params->setTerrainFirstColor(ui->pushButton_4->text().toUtf8().constData());
    }
    if(ui->pushButton_5->text() != "Color")
    {
        params->setTerrainSecondColor(ui->pushButton_5->text().toUtf8().constData());
    }

	if(ui->pushButton_6->text() != "Color")
    {
        params->setMountainFirstColor(ui->pushButton_6->text().toUtf8().constData());
    }
    if(ui->pushButton_7->text() != "Color")
    {
        params->setMountainSecondColor(ui->pushButton_7->text().toUtf8().constData());
    }

    //debug messages
    qDebug() << params->getRadius();
    qDebug() << params->getWaterFraction();
    qDebug() << params->getSeed();
	qDebug() << QString::fromStdString(params->getWaterFirstColor());
	qDebug() << QString::fromStdString(params->getWaterSecondColor());
	qDebug() << QString::fromStdString(params->getTerrainFirstColor());
	qDebug() << QString::fromStdString(params->getTerrainSecondColor());
	qDebug() << QString::fromStdString(params->getMountainFirstColor());
	qDebug() << QString::fromStdString(params->getMountainSecondColor());

    for (std::vector<std::pair <float, float> >::const_iterator iter = params->getFrequencyAmplitude().begin(); iter != params->getFrequencyAmplitude().end(); ++iter)
	{
		qDebug() << iter->first <<", " << iter->second;
    }
 /*   for (std::vector<float>::const_iterator iter = params->getFrequency().begin(); iter != params->getFrequency().end(); ++iter)
    {
        qDebug() << "Frequency:" << *iter;
    }
    for (std::vector<float>::const_iterator iter = params->getAmplitude().begin(); iter != params->getAmplitude().end(); ++iter)
    {
        qDebug() << "Amplitude: " << *iter;
    }*/

    for (std::vector<std::pair <std::string, int> >::const_iterator iter = params->getMeshLocObjAmount().begin(); iter != params->getMeshLocObjAmount().end(); ++iter)
    {
        qDebug() << QString::fromStdString(iter->first) <<", " << iter->second;
    }
 /*   for (std::vector<std::string>::const_iterator iter = params->getMeshLocations().begin(); iter != params->getMeshLocations().end(); ++iter)
    {
        qDebug() << "Mesh path:" << QString::fromStdString(*iter);
    }
    for (std::vector<int>::const_iterator iter = params->getObjectAmount().begin(); iter != params->getObjectAmount().end(); ++iter)
    {
        qDebug() << "Amount: " << *iter;
    }*/

	mySphere = new PSphere(100, 40, *params);
	rendering = new initOgre();
	rendering->start();
	rendering->setSceneAndRun(mySphere);
	mySphere->exportEquirectangularMap(512, 256, "TestFile.png");
	delete mySphere;
    rendering->cleanup();

}

void MainWindow::on_pushButton_2_clicked()
{
    QColor rg = QColorDialog::getColor(Qt::white,this, "Text Color",  QColorDialog::DontUseNativeDialog);
    QString qss = QString("background-color: %1").arg(rg.name());
    ui->pushButton_2->setStyleSheet(qss);
    ui->pushButton_2->setText(""+rg.name());
    qDebug() << "Color chosen: "+rg.name();
}

void MainWindow::on_pushButton_3_clicked()
{
    QColor rg = QColorDialog::getColor(Qt::white,this, "Text Color",  QColorDialog::DontUseNativeDialog);
    QString qss = QString("background-color: %1").arg(rg.name());
    ui->pushButton_3->setStyleSheet(qss);
    ui->pushButton_3->setText(""+rg.name());
    qDebug() << "Color chosen: "+rg.name();
}

void MainWindow::on_pushButton_4_clicked()
{
    QColor rg = QColorDialog::getColor(Qt::white,this, "Text Color",  QColorDialog::DontUseNativeDialog);
    QString qss = QString("background-color: %1").arg(rg.name());
    ui->pushButton_4->setStyleSheet(qss);
    ui->pushButton_4->setText(""+rg.name());
    qDebug() << "Color chosen: "+rg.name();
}

void MainWindow::on_pushButton_5_clicked()
{
    QColor rg = QColorDialog::getColor(Qt::white,this, "Text Color",  QColorDialog::DontUseNativeDialog);
    QString qss = QString("background-color: %1").arg(rg.name());
    ui->pushButton_5->setStyleSheet(qss);
    ui->pushButton_5->setText(""+rg.name());
    qDebug() << "Color chosen: "+rg.name();
}

void MainWindow::on_pushButton_6_clicked()
{
    QColor rg = QColorDialog::getColor(Qt::white,this, "Text Color",  QColorDialog::DontUseNativeDialog);
    QString qss = QString("background-color: %1").arg(rg.name());
    ui->pushButton_6->setStyleSheet(qss);
    ui->pushButton_6->setText(""+rg.name());
    qDebug() << "Color chosen: "+rg.name();
}

void MainWindow::on_pushButton_7_clicked()
{
    QColor rg = QColorDialog::getColor(Qt::white,this, "Text Color",  QColorDialog::DontUseNativeDialog);
    QString qss = QString("background-color: %1").arg(rg.name());
    ui->pushButton_7->setStyleSheet(qss);
    ui->pushButton_7->setText(""+rg.name());
    qDebug() << "Color chosen: "+rg.name();
}

void MainWindow::on_pushButton_8_clicked()
{
    openNewWindow();
}

void MainWindow::openNewWindow()
{
    dialog = new FreqAmpDialog();
    //add items from ResourceParameter vector to listwidget
    dialog->instantiateList(params->getFrequencyAmplitude());
	std::string frequencyAmplitude;
	if(dialog->exec())
    {
        //clear ResourceParameter vector
        params->emptyFrequencyAmplitude();
		for(int i=0; i<dialog->getThem()->count(); i++)
		{
			QStringList values = dialog->getThem()->item(i)->text().split(",");
            //put values to ResourceParameter vector
            //setAmps( values.value(0).toFloat(),  values.value(1).toFloat());
			frequencyAmplitude += values.value(0).toStdString() + ' ' +  values.value(1).toStdString() + ' ';
		}
		params->setFrequencyAmplitude(frequencyAmplitude, ' ');
	}
}

void MainWindow::setAmps(float p_val1, float p_val2)
{
    //params->setFrequencyAmplitude(p_val1, p_val2);

    //alternate way:
    //params->setFrequency(p_val1);
    //params->setAmplitude(p_val2);
}

void MainWindow::on_pushButton_9_clicked()
{
    meshdialog = new MeshDialog();
    //add items from ResourceParameter vector to listwidget
    meshdialog->instantiateList(params->getMeshLocObjAmount());
    if(meshdialog->exec())
    {
        //clear ResourceParameter vector
        params->emptyMeshLocObjAmount();
        for(int i=0; i<meshdialog->getMeshes()->count(); i++)
        {
            QStringList values = meshdialog->getMeshes()->item(i)->text().split(",");

            //put values to ResourceParameter vector
            setMeshes( values.value(0),  values.value(1).toInt());
        }
    }
}

void MainWindow::setMeshes(QString p_path, int p_count)
{
    params->setMeshLocObjAmount(p_path.toStdString(), p_count);

    //alternate way:
    //params->setMeshLocation(p_path.toStdString());
    //params->setObjectAmount(p_count);
}

void MainWindow::on_pushButton_10_clicked()
{
    QString filename = QFileDialog::getSaveFileName(this, "Save image", "../", "*.png" )+".png";
    qDebug() << "save as : " + filename;

    //unsigned short
    QString string = ui->comboBox->currentText();

    QStringList values = string.split(" x ");

    unsigned short width =  values[0].toUShort();
    unsigned short height =  values[1].toUShort();

    qDebug() << "width: " << width << ", height: " << height ;

    //create planet
    //push to pshere export-method with filename + resolution
}

void MainWindow::on_pushButton_11_clicked()
{
 /*   QImage image = QImage::fromData(unsigned char array, QImage::Format_RGB888);

    QGraphicsScene scene;
    scene.addItem(image);

    ui->graphicsView->setScene(scene);
    ui->graphicsView->show();
*/
}
<commit_msg>save image<commit_after>/* The MIT License (MIT)
 *
 * Copyright (c) 2015 Giovanni Ortolani, Taneli Mikkonen, Pingjiang Li, Tommi Puolamaa, Mitra Vahida
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE. */

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "freqampdialog.h"
#include "../ResourceParameter.h"
#include <QDebug>
#include <QColorDialog>
#include <QVectorIterator>
#include <QtMath>
#include <QFileDialog>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    setFixedSize(geometry().width(), geometry().height());

    //Regex validators to handle 2 decimal float values from 0-100
    QRegExp rex("[0-9][0-9]\\.\\d{0,2}|[0-9]\\.\\d{0,2}|(100)");
    QRegExpValidator *radiusvalidator = new QRegExpValidator(rex, this);

    ui->lineEdit->setValidator( radiusvalidator );

    QRegExp rex2("[0-9][0-9]\\.\\d{0,2}|[0-9]\\.\\d{0,2}|(100)");
    QRegExpValidator *watervalidator = new QRegExpValidator(rex2, this);

    ui->lineEdit_2->setValidator( watervalidator );

    //regex to handle max value for lineEdit to be 2*32-1 (UINT_MAX)
    QRegExp rx("^(\\d|\\d{1,9}|[0-3]\\d{1,9}|4[0-1]\\d{8}|42[0-8]\\d{7}|429[0-3]\\d{6}|4294[0-8]\\d{5}|42949[0-5]\\d{4}|429496[0-6]\\d{3}|4294967[0-1]\\d{2}|429496729[0-5])$");
    QValidator *validator = new QRegExpValidator(rx, this);
    ui->lineEdit_3->setValidator(validator);

	//set default parameters for now::
	/*vector<float> frequency;
	frequency.push_back(0.4);
	frequency.push_back(0.06666);
	vector <float> amplitude;
	amplitude.push_back(0.02);
	amplitude.push_back(0.006666);*/

	std::string frequencyAmplitude = "1.0 0.02 0.3 0.008 0.1 0.005 0.06666 0.006666";
    std::vector < std::pair < std::string, int > > meshlocs;
    meshlocs.push_back(std::make_pair("media/models/ram.mesh", 1));
    meshlocs.push_back(std::make_pair("media/models/asteroid.mesh", 1));

	float waterfraction = 0.6;
	float radius = 7.5;
    int seed = 60;

    ui->lineEdit->setText(""+QString::number(radius));
    ui->lineEdit_2->setText(""+QString::number(waterfraction*100));
    ui->lineEdit_3->setText(""+QString::number(seed));

    params = new std::ResourceParameter((std::string)"#00FF00",(std::string)"#FACD00",(std::string)"#32CDFF"
        ,(std::string)"#64FFFF",(std::string)"#B4B4B4",(std::string)"#FFFFFF",waterfraction,radius,seed,frequencyAmplitude, meshlocs);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
	if(!ui->lineEdit->text().isEmpty())
    {
        float radius = ui->lineEdit->text().toFloat();
        params->setRadius(radius);
    }

    if(!ui->lineEdit_2->text().isEmpty())
    {
        float waterfraction = (ui->lineEdit_2->text().toFloat())/100;
        params->setWaterFraction(waterfraction);
    }
    if(!ui->lineEdit_3->text().isEmpty())
    {
        int seed = ui->lineEdit_3->text().toInt();
        params->setSeed(seed);
    }

    if(ui->pushButton_2->text() != "Color")
    {
        params->setWaterFirstColor(ui->pushButton_2->text().toUtf8().constData());
    }
    if(ui->pushButton_3->text() != "Color")
    {
        params->setWaterSecondColor(ui->pushButton_3->text().toUtf8().constData());
    }

    if(ui->pushButton_4->text() != "Color")
    {
        params->setTerrainFirstColor(ui->pushButton_4->text().toUtf8().constData());
    }
    if(ui->pushButton_5->text() != "Color")
    {
        params->setTerrainSecondColor(ui->pushButton_5->text().toUtf8().constData());
    }

	if(ui->pushButton_6->text() != "Color")
    {
        params->setMountainFirstColor(ui->pushButton_6->text().toUtf8().constData());
    }
    if(ui->pushButton_7->text() != "Color")
    {
        params->setMountainSecondColor(ui->pushButton_7->text().toUtf8().constData());
    }

    //debug messages
    qDebug() << params->getRadius();
    qDebug() << params->getWaterFraction();
    qDebug() << params->getSeed();
	qDebug() << QString::fromStdString(params->getWaterFirstColor());
	qDebug() << QString::fromStdString(params->getWaterSecondColor());
	qDebug() << QString::fromStdString(params->getTerrainFirstColor());
	qDebug() << QString::fromStdString(params->getTerrainSecondColor());
	qDebug() << QString::fromStdString(params->getMountainFirstColor());
	qDebug() << QString::fromStdString(params->getMountainSecondColor());

    for (std::vector<std::pair <float, float> >::const_iterator iter = params->getFrequencyAmplitude().begin(); iter != params->getFrequencyAmplitude().end(); ++iter)
	{
		qDebug() << iter->first <<", " << iter->second;
    }
 /*   for (std::vector<float>::const_iterator iter = params->getFrequency().begin(); iter != params->getFrequency().end(); ++iter)
    {
        qDebug() << "Frequency:" << *iter;
    }
    for (std::vector<float>::const_iterator iter = params->getAmplitude().begin(); iter != params->getAmplitude().end(); ++iter)
    {
        qDebug() << "Amplitude: " << *iter;
    }*/

    for (std::vector<std::pair <std::string, int> >::const_iterator iter = params->getMeshLocObjAmount().begin(); iter != params->getMeshLocObjAmount().end(); ++iter)
    {
        qDebug() << QString::fromStdString(iter->first) <<", " << iter->second;
    }
 /*   for (std::vector<std::string>::const_iterator iter = params->getMeshLocations().begin(); iter != params->getMeshLocations().end(); ++iter)
    {
        qDebug() << "Mesh path:" << QString::fromStdString(*iter);
    }
    for (std::vector<int>::const_iterator iter = params->getObjectAmount().begin(); iter != params->getObjectAmount().end(); ++iter)
    {
        qDebug() << "Amount: " << *iter;
    }*/

	mySphere = new PSphere(100, 40, *params);
	rendering = new initOgre();
	rendering->start();
	rendering->setSceneAndRun(mySphere);
    //mySphere->exportEquirectangularMap(512, 256, "TestFile.png");
	delete mySphere;
    rendering->cleanup();

}

void MainWindow::on_pushButton_2_clicked()
{
    QColor rg = QColorDialog::getColor(Qt::white,this, "Text Color",  QColorDialog::DontUseNativeDialog);
    QString qss = QString("background-color: %1").arg(rg.name());
    ui->pushButton_2->setStyleSheet(qss);
    ui->pushButton_2->setText(""+rg.name());
    qDebug() << "Color chosen: "+rg.name();
}

void MainWindow::on_pushButton_3_clicked()
{
    QColor rg = QColorDialog::getColor(Qt::white,this, "Text Color",  QColorDialog::DontUseNativeDialog);
    QString qss = QString("background-color: %1").arg(rg.name());
    ui->pushButton_3->setStyleSheet(qss);
    ui->pushButton_3->setText(""+rg.name());
    qDebug() << "Color chosen: "+rg.name();
}

void MainWindow::on_pushButton_4_clicked()
{
    QColor rg = QColorDialog::getColor(Qt::white,this, "Text Color",  QColorDialog::DontUseNativeDialog);
    QString qss = QString("background-color: %1").arg(rg.name());
    ui->pushButton_4->setStyleSheet(qss);
    ui->pushButton_4->setText(""+rg.name());
    qDebug() << "Color chosen: "+rg.name();
}

void MainWindow::on_pushButton_5_clicked()
{
    QColor rg = QColorDialog::getColor(Qt::white,this, "Text Color",  QColorDialog::DontUseNativeDialog);
    QString qss = QString("background-color: %1").arg(rg.name());
    ui->pushButton_5->setStyleSheet(qss);
    ui->pushButton_5->setText(""+rg.name());
    qDebug() << "Color chosen: "+rg.name();
}

void MainWindow::on_pushButton_6_clicked()
{
    QColor rg = QColorDialog::getColor(Qt::white,this, "Text Color",  QColorDialog::DontUseNativeDialog);
    QString qss = QString("background-color: %1").arg(rg.name());
    ui->pushButton_6->setStyleSheet(qss);
    ui->pushButton_6->setText(""+rg.name());
    qDebug() << "Color chosen: "+rg.name();
}

void MainWindow::on_pushButton_7_clicked()
{
    QColor rg = QColorDialog::getColor(Qt::white,this, "Text Color",  QColorDialog::DontUseNativeDialog);
    QString qss = QString("background-color: %1").arg(rg.name());
    ui->pushButton_7->setStyleSheet(qss);
    ui->pushButton_7->setText(""+rg.name());
    qDebug() << "Color chosen: "+rg.name();
}

void MainWindow::on_pushButton_8_clicked()
{
    openNewWindow();
}

void MainWindow::openNewWindow()
{
    dialog = new FreqAmpDialog();
    //add items from ResourceParameter vector to listwidget
    dialog->instantiateList(params->getFrequencyAmplitude());
	std::string frequencyAmplitude;
	if(dialog->exec())
    {
        //clear ResourceParameter vector
        params->emptyFrequencyAmplitude();
		for(int i=0; i<dialog->getThem()->count(); i++)
		{
			QStringList values = dialog->getThem()->item(i)->text().split(",");
            //put values to ResourceParameter vector
            //setAmps( values.value(0).toFloat(),  values.value(1).toFloat());
			frequencyAmplitude += values.value(0).toStdString() + ' ' +  values.value(1).toStdString() + ' ';
		}
		params->setFrequencyAmplitude(frequencyAmplitude, ' ');
	}
}

void MainWindow::setAmps(float p_val1, float p_val2)
{
    //params->setFrequencyAmplitude(p_val1, p_val2);

    //alternate way:
    //params->setFrequency(p_val1);
    //params->setAmplitude(p_val2);
}

void MainWindow::on_pushButton_9_clicked()
{
    meshdialog = new MeshDialog();
    //add items from ResourceParameter vector to listwidget
    meshdialog->instantiateList(params->getMeshLocObjAmount());
    if(meshdialog->exec())
    {
        //clear ResourceParameter vector
        params->emptyMeshLocObjAmount();
        for(int i=0; i<meshdialog->getMeshes()->count(); i++)
        {
            QStringList values = meshdialog->getMeshes()->item(i)->text().split(",");

            //put values to ResourceParameter vector
            setMeshes( values.value(0),  values.value(1).toInt());
        }
    }
}

void MainWindow::setMeshes(QString p_path, int p_count)
{
    params->setMeshLocObjAmount(p_path.toStdString(), p_count);

    //alternate way:
    //params->setMeshLocation(p_path.toStdString());
    //params->setObjectAmount(p_count);
}

void MainWindow::on_pushButton_10_clicked()
{
    QString filename = QFileDialog::getSaveFileName(this, "Save image", "../", "*.png" )+".png";
    qDebug() << "save as : " + filename;

    //unsigned short
    QString string = ui->comboBox->currentText();

    QStringList values = string.split(" x ");

    unsigned short width =  values[0].toUShort();
    unsigned short height =  values[1].toUShort();

    qDebug() << "width: " << width << ", height: " << height ;

    //create planet
    mySphere = new PSphere(100, 40, *params);
    //push to pshere export-method with filename + resolution
    mySphere->exportEquirectangularMap(width, height, filename);

}

void MainWindow::on_pushButton_11_clicked()
{
 /*   QImage image = QImage::fromData(unsigned char array, QImage::Format_RGB888);

    QGraphicsScene scene;
    scene.addItem(image);

    ui->graphicsView->setScene(scene);
    ui->graphicsView->show();
*/
}
<|endoftext|>


<commit_before>/**
  * Touhou Community Reliant Automatic Patcher
  * Main DLL
  *
  * ----
  *
  * Persistent string storage, and translation of hardcoded strings.
  */

#include "thcrap.h"
#include <unordered_map>

/// Detour chains
/// -------------
W32U8_DETOUR_CHAIN_DEF(MessageBox);
/// -------------

// Since we can't use the jsondata module to make this repatchable,
// we only need to keep the last parsed JSON object around to
// provide the "backing memory" for the ID strings.
json_t *backing_obj = nullptr;

// Length-prefixed string object used for persistent storage
typedef struct {
	size_t len;
	char str;
} storage_string_t;

std::unordered_map<size_t, storage_string_t *> strings_storage;

SRWLOCK stringlocs_srwlock = {SRWLOCK_INIT};
std::unordered_map<const char *, const char *> stringlocs;

#define addr_key_len 2 + (sizeof(void*) * 2) + 1

void stringlocs_reparse(void)
{
	json_t* new_obj = stack_game_json_resolve("stringlocs.js", NULL);
	const char *key;
	const json_t *val;

	AcquireSRWLockExclusive(&stringlocs_srwlock);
	stringlocs.clear();

	json_object_foreach(new_obj, key, val) {
		// TODO: For now, we're nagging developers with one message box for
		// every single parse error. It'd certainly be better if we gathered
		// all errors into a single message box to be printed at the end of
		// the parsing, and even had a somewhat generic solution if we do
		// more of these conversions.
#define stringlocs_log_error(msg) \
	log_mboxf(NULL, MB_OK | MB_ICONEXCLAMATION, \
		"Error parsing stringlocs.js: \"%s\" " msg".", key, sizeof(size_t) * 8 \
	)

		if(!json_is_string(val)) {
			stringlocs_log_error("must be a JSON string");
			continue;
		}
		str_address_ret_t addr_ret;
		auto *addr = (const char *)str_address_value(key, NULL, &addr_ret);
		if(addr_ret.error == STR_ADDRESS_ERROR_NONE) {
			stringlocs[addr] = json_string_value(val);
		}
		if(addr_ret.error & STR_ADDRESS_ERROR_OVERFLOW) {
			stringlocs_log_error("exceeds %d bits");
		}
		if(addr_ret.error & STR_ADDRESS_ERROR_GARBAGE) {
			stringlocs_log_error("has garbage at the end");
		}
#undef stringlocs_log_error
	}

	json_decref(backing_obj);
	backing_obj = new_obj;

	ReleaseSRWLockExclusive(&stringlocs_srwlock);
}

const char* strings_id(const char *str)
{
	const char *ret = nullptr;
	AcquireSRWLockShared(&stringlocs_srwlock);
	auto id_key = stringlocs.find(str);
	if(id_key != stringlocs.end()) {
		ret = id_key->second;
	}
	ReleaseSRWLockShared(&stringlocs_srwlock);
	return ret;
}

const json_t* strings_get(const char *id)
{
	return json_object_get(jsondata_get("stringdefs.js"), id);
}

stringref_t strings_get_fallback(const string_named_t& sn)
{
	auto ret = strings_get(sn.id);
	if(!json_is_string(ret)) {
		return sn.fallback;
	}
	return ret;
}

const char* strings_lookup(const char *in, size_t *out_len)
{
	const char *ret = in;

	if(!in) {
		return in;
	}

	AcquireSRWLockShared(&stringlocs_srwlock);
	auto id = strings_id(in);
	if(id) {
		auto *new_str = json_string_value(strings_get(id));
		if(new_str && new_str[0]) {
			ret = new_str;
		}
	}
	ReleaseSRWLockShared(&stringlocs_srwlock);

	if(out_len) {
		*out_len = strlen(ret);
	}
	return ret;
}

void strings_va_lookup(va_list va, const char *format)
{
	const char *p = format;
	while(*p) {
		printf_format_t fmt;
		int i;

		// Skip characters before '%'
		for(; *p && *p != '%'; p++);
		if(!*p) {
			break;
		}
		// *p == '%' here
		p++;

		// output a single '%' character
		if(*p == '%') {
			p++;
			continue;
		}
		p = printf_format_parse(&fmt, p);
		for(i = 0; i < fmt.argc_before_type; i++) {
			va_arg(va, int);
		}
		if(fmt.type == 's' || fmt.type == 'S') {
			*(const char**)va = strings_lookup(*(const char**)va, NULL);
		}
		for(i = 0; i < fmt.type_size_in_ints; i++) {
			va_arg(va, int);
		}
	}
}

char* strings_storage_get(const size_t slot, size_t min_len)
{
	auto stored = strings_storage.find(slot);
	auto *ret = stored != strings_storage.end() ? stored->second : nullptr;

	// MSVCRT's realloc implementation moves the buffer every time, even if the
	// new length is shorter...
	if(ret == nullptr || (min_len && ret->len < min_len)) {
		auto *ret_new = (storage_string_t*)realloc(ret, min_len + sizeof(storage_string_t));
		// Yes, this correctly handles a realloc failure.
		if(ret_new) {
			ret_new->len = min_len;
			if(!ret) {
				ret_new->str = 0;
			}
			strings_storage[slot] = ret_new;
			ret = ret_new;
		}
	}
	if(ret) {
		return &ret->str;
	}
	return nullptr;
}

const char* strings_vsprintf(const size_t slot, const char *format, va_list va)
{
	char *ret = NULL;
	size_t str_len;

	format = strings_lookup(format, NULL);
	strings_va_lookup(va, format);

	if(!format) {
		return NULL;
	}
	str_len = _vscprintf(format, va) + 1;

	ret = strings_storage_get(slot, str_len);
	if(ret) {
		vsprintf(ret, format, va);
		return ret;
	}
	// Try to save the situation at least somewhat...
	return format;
}

const char* strings_vsprintf_msvcrt14(const char *format, const size_t slot, va_list va)
{
	return strings_vsprintf(slot, format, va);
}

const char* strings_sprintf(const size_t slot, const char *format, ...)
{
	va_list va;
	const char *ret;
	va_start(va, format);
	ret = strings_vsprintf(slot, format, va);
	return ret;
}

const char* strings_strclr(const size_t slot)
{
	char *ret = strings_storage_get(slot, 0);
	if(ret) {
		ret[0] = 0;
	}
	return ret;
}

const char* strings_strcat(const size_t slot, const char *src)
{
	char *ret = strings_storage_get(slot, 0);
	size_t ret_len = strlen(ret);
	size_t src_len;

	src = strings_lookup(src, &src_len);

	ret = strings_storage_get(slot, ret_len + src_len + 1);
	if(ret) {
		strncpy(ret + ret_len, src, src_len + 1);
		return ret;
	}
	// Try to save the situation at least somewhat...
	return src;
}

const char* strings_replace(const size_t slot, const char *src, const char *dst)
{
	char *ret = strings_storage_get(slot, 0);
	dst = dst ? dst : "";
	if(src && ret) {
		size_t src_len = strlen(src);
		size_t dst_len = strlen(dst);
		while(ret) {
			char *src_pos = NULL;
			char *copy_pos = NULL;
			char *rest_pos = NULL;
			size_t ret_len = strlen(ret);
			// We do this first since the string address might change after
			// reallocation, thus invalidating the strstr() result
			ret = strings_storage_get(slot, ret_len + dst_len);
			if(!ret) {
				break;
			}
			src_pos = strstr(ret, src);
			if(!src_pos) {
				break;
			}
			copy_pos = src_pos + dst_len;
			rest_pos = src_pos + src_len;
			memmove(copy_pos, rest_pos, strlen(rest_pos) + 1);
			memcpy(src_pos, dst, dst_len);
		}
	}
	// Try to save the situation at least somewhat...
	return ret ? ret : dst;
}

/// String lookup hooks
/// -------------------
int WINAPI strings_MessageBoxA(
	HWND hWnd,
	LPCSTR lpText,
	LPCSTR lpCaption,
	UINT uType
)
{
	lpText = strings_lookup(lpText, NULL);
	lpCaption = strings_lookup(lpCaption, NULL);
	return chain_MessageBoxU(hWnd, lpText, lpCaption, uType);
}
/// -------------------

void strings_mod_init(void)
{
	jsondata_add("stringdefs.js");
	stringlocs_reparse();
}

void strings_mod_detour(void)
{
	detour_chain("user32.dll", 1,
		"MessageBoxA", strings_MessageBoxA, &chain_MessageBoxU,
		NULL
	);
}

void strings_mod_repatch(json_t *files_changed)
{
	const char *key;
	const json_t *val;
	json_object_foreach(files_changed, key, val) {
		if(strstr(key, "/stringlocs.")) {
			stringlocs_reparse();
		}
	}
}

void strings_mod_exit(void)
{
	for(auto& i : strings_storage) {
		SAFE_FREE(i.second);
	}
	strings_storage.clear();
	stringlocs.clear();
	backing_obj = json_decref_safe(backing_obj);
}
<commit_msg>Allow changing hardcoded strings for FindFirstFileA calls<commit_after>/**
  * Touhou Community Reliant Automatic Patcher
  * Main DLL
  *
  * ----
  *
  * Persistent string storage, and translation of hardcoded strings.
  */

#include "thcrap.h"
#include <unordered_map>

/// Detour chains
/// -------------
W32U8_DETOUR_CHAIN_DEF(MessageBox);
W32U8_DETOUR_CHAIN_DEF(FindFirstFile);
/// -------------

// Since we can't use the jsondata module to make this repatchable,
// we only need to keep the last parsed JSON object around to
// provide the "backing memory" for the ID strings.
json_t *backing_obj = nullptr;

// Length-prefixed string object used for persistent storage
typedef struct {
	size_t len;
	char str;
} storage_string_t;

std::unordered_map<size_t, storage_string_t *> strings_storage;

SRWLOCK stringlocs_srwlock = {SRWLOCK_INIT};
std::unordered_map<const char *, const char *> stringlocs;

#define addr_key_len 2 + (sizeof(void*) * 2) + 1

void stringlocs_reparse(void)
{
	json_t* new_obj = stack_game_json_resolve("stringlocs.js", NULL);
	const char *key;
	const json_t *val;

	AcquireSRWLockExclusive(&stringlocs_srwlock);
	stringlocs.clear();

	json_object_foreach(new_obj, key, val) {
		// TODO: For now, we're nagging developers with one message box for
		// every single parse error. It'd certainly be better if we gathered
		// all errors into a single message box to be printed at the end of
		// the parsing, and even had a somewhat generic solution if we do
		// more of these conversions.
#define stringlocs_log_error(msg) \
	log_mboxf(NULL, MB_OK | MB_ICONEXCLAMATION, \
		"Error parsing stringlocs.js: \"%s\" " msg".", key, sizeof(size_t) * 8 \
	)

		if(!json_is_string(val)) {
			stringlocs_log_error("must be a JSON string");
			continue;
		}
		str_address_ret_t addr_ret;
		auto *addr = (const char *)str_address_value(key, NULL, &addr_ret);
		if(addr_ret.error == STR_ADDRESS_ERROR_NONE) {
			stringlocs[addr] = json_string_value(val);
		}
		if(addr_ret.error & STR_ADDRESS_ERROR_OVERFLOW) {
			stringlocs_log_error("exceeds %d bits");
		}
		if(addr_ret.error & STR_ADDRESS_ERROR_GARBAGE) {
			stringlocs_log_error("has garbage at the end");
		}
#undef stringlocs_log_error
	}

	json_decref(backing_obj);
	backing_obj = new_obj;

	ReleaseSRWLockExclusive(&stringlocs_srwlock);
}

const char* strings_id(const char *str)
{
	const char *ret = nullptr;
	AcquireSRWLockShared(&stringlocs_srwlock);
	auto id_key = stringlocs.find(str);
	if(id_key != stringlocs.end()) {
		ret = id_key->second;
	}
	ReleaseSRWLockShared(&stringlocs_srwlock);
	return ret;
}

const json_t* strings_get(const char *id)
{
	return json_object_get(jsondata_get("stringdefs.js"), id);
}

stringref_t strings_get_fallback(const string_named_t& sn)
{
	auto ret = strings_get(sn.id);
	if(!json_is_string(ret)) {
		return sn.fallback;
	}
	return ret;
}

const char* strings_lookup(const char *in, size_t *out_len)
{
	const char *ret = in;

	if(!in) {
		return in;
	}

	AcquireSRWLockShared(&stringlocs_srwlock);
	auto id = strings_id(in);
	if(id) {
		auto *new_str = json_string_value(strings_get(id));
		if(new_str && new_str[0]) {
			ret = new_str;
		}
	}
	ReleaseSRWLockShared(&stringlocs_srwlock);

	if(out_len) {
		*out_len = strlen(ret);
	}
	return ret;
}

void strings_va_lookup(va_list va, const char *format)
{
	const char *p = format;
	while(*p) {
		printf_format_t fmt;
		int i;

		// Skip characters before '%'
		for(; *p && *p != '%'; p++);
		if(!*p) {
			break;
		}
		// *p == '%' here
		p++;

		// output a single '%' character
		if(*p == '%') {
			p++;
			continue;
		}
		p = printf_format_parse(&fmt, p);
		for(i = 0; i < fmt.argc_before_type; i++) {
			va_arg(va, int);
		}
		if(fmt.type == 's' || fmt.type == 'S') {
			*(const char**)va = strings_lookup(*(const char**)va, NULL);
		}
		for(i = 0; i < fmt.type_size_in_ints; i++) {
			va_arg(va, int);
		}
	}
}

char* strings_storage_get(const size_t slot, size_t min_len)
{
	auto stored = strings_storage.find(slot);
	auto *ret = stored != strings_storage.end() ? stored->second : nullptr;

	// MSVCRT's realloc implementation moves the buffer every time, even if the
	// new length is shorter...
	if(ret == nullptr || (min_len && ret->len < min_len)) {
		auto *ret_new = (storage_string_t*)realloc(ret, min_len + sizeof(storage_string_t));
		// Yes, this correctly handles a realloc failure.
		if(ret_new) {
			ret_new->len = min_len;
			if(!ret) {
				ret_new->str = 0;
			}
			strings_storage[slot] = ret_new;
			ret = ret_new;
		}
	}
	if(ret) {
		return &ret->str;
	}
	return nullptr;
}

const char* strings_vsprintf(const size_t slot, const char *format, va_list va)
{
	char *ret = NULL;
	size_t str_len;

	format = strings_lookup(format, NULL);
	strings_va_lookup(va, format);

	if(!format) {
		return NULL;
	}
	str_len = _vscprintf(format, va) + 1;

	ret = strings_storage_get(slot, str_len);
	if(ret) {
		vsprintf(ret, format, va);
		return ret;
	}
	// Try to save the situation at least somewhat...
	return format;
}

const char* strings_vsprintf_msvcrt14(const char *format, const size_t slot, va_list va)
{
	return strings_vsprintf(slot, format, va);
}

const char* strings_sprintf(const size_t slot, const char *format, ...)
{
	va_list va;
	const char *ret;
	va_start(va, format);
	ret = strings_vsprintf(slot, format, va);
	return ret;
}

const char* strings_strclr(const size_t slot)
{
	char *ret = strings_storage_get(slot, 0);
	if(ret) {
		ret[0] = 0;
	}
	return ret;
}

const char* strings_strcat(const size_t slot, const char *src)
{
	char *ret = strings_storage_get(slot, 0);
	size_t ret_len = strlen(ret);
	size_t src_len;

	src = strings_lookup(src, &src_len);

	ret = strings_storage_get(slot, ret_len + src_len + 1);
	if(ret) {
		strncpy(ret + ret_len, src, src_len + 1);
		return ret;
	}
	// Try to save the situation at least somewhat...
	return src;
}

const char* strings_replace(const size_t slot, const char *src, const char *dst)
{
	char *ret = strings_storage_get(slot, 0);
	dst = dst ? dst : "";
	if(src && ret) {
		size_t src_len = strlen(src);
		size_t dst_len = strlen(dst);
		while(ret) {
			char *src_pos = NULL;
			char *copy_pos = NULL;
			char *rest_pos = NULL;
			size_t ret_len = strlen(ret);
			// We do this first since the string address might change after
			// reallocation, thus invalidating the strstr() result
			ret = strings_storage_get(slot, ret_len + dst_len);
			if(!ret) {
				break;
			}
			src_pos = strstr(ret, src);
			if(!src_pos) {
				break;
			}
			copy_pos = src_pos + dst_len;
			rest_pos = src_pos + src_len;
			memmove(copy_pos, rest_pos, strlen(rest_pos) + 1);
			memcpy(src_pos, dst, dst_len);
		}
	}
	// Try to save the situation at least somewhat...
	return ret ? ret : dst;
}

/// String lookup hooks
/// -------------------
int WINAPI strings_MessageBoxA(
	HWND hWnd,
	LPCSTR lpText,
	LPCSTR lpCaption,
	UINT uType
)
{
	lpText = strings_lookup(lpText, NULL);
	lpCaption = strings_lookup(lpCaption, NULL);
	return chain_MessageBoxU(hWnd, lpText, lpCaption, uType);
}

HANDLE WINAPI strings_FindFirstFileA(
	LPCSTR lpFileName,
	LPWIN32_FIND_DATAA lpFindFileData
)
{
	return chain_FindFirstFileU(strings_lookup(lpFileName, NULL), lpFindFileData);
}
/// -------------------

void strings_mod_init(void)
{
	jsondata_add("stringdefs.js");
	stringlocs_reparse();
}

void strings_mod_detour(void)
{
	detour_chain("user32.dll", 1,
		"MessageBoxA", strings_MessageBoxA, &chain_MessageBoxU,
		NULL
	);
	detour_chain("kernel32.dll", 1,
		"FindFirstFileA", strings_FindFirstFileA, &chain_FindFirstFileU,
		NULL
	);
}

void strings_mod_repatch(json_t *files_changed)
{
	const char *key;
	const json_t *val;
	json_object_foreach(files_changed, key, val) {
		if(strstr(key, "/stringlocs.")) {
			stringlocs_reparse();
		}
	}
}

void strings_mod_exit(void)
{
	for(auto& i : strings_storage) {
		SAFE_FREE(i.second);
	}
	strings_storage.clear();
	stringlocs.clear();
	backing_obj = json_decref_safe(backing_obj);
}
<|endoftext|>