<commit_before>// Scintilla source code edit control
/** @file LexLisp.cxx
 ** Lexer for Lisp.
 ** Written by Alexey Yutkin.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static inline bool isLispoperator(char ch) {
	if (isascii(ch) && isalnum(ch))
		return false;
	if (ch == '\'' || ch == '(' || ch == ')' )
		return true;
	return false;
}

static inline bool isLispwordstart(char ch) {
	return isascii(ch) && ch != ';'  && !isspacechar(ch) && !isLispoperator(ch) &&
		ch != '\n' && ch != '\r' &&  ch != '\"';
}

static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
	PLATFORM_ASSERT(end >= start);
	char s[100];
	unsigned int i;
	bool digit_flag = true;
	for (i = 0; (i < end - start + 1) && (i < 99); i++) {
		s[i] = styler[start + i];
		s[i + 1] = '\0';
		if (!isdigit(s[i]) && (s[i] != '.')) digit_flag = false;
	}
	char chAttr = SCE_LISP_IDENTIFIER;

	if(digit_flag) chAttr = SCE_LISP_NUMBER;
	else {
		if (keywords.InList(s)) {
			chAttr = SCE_LISP_KEYWORD;
		}
	}
	styler.ColourTo(end, chAttr);
	return;
}

static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];

	styler.StartAt(startPos);

	int state = initStyle;
	char chNext = styler[startPos];
	unsigned int lengthDoc = startPos + length;
	styler.StartSegment(startPos);
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			i += 1;
			continue;
		}

		if (state == SCE_LISP_DEFAULT) {
			if (isLispwordstart(ch)) {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_IDENTIFIER;
			}
			else if (ch == ';') {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_COMMENT;
			}
			else if (isLispoperator(ch) || ch=='\'') {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LISP_OPERATOR);
			}
			else if (ch == '\"') {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_STRING;
			}
		} else if (state == SCE_LISP_IDENTIFIER) {
			if (!isLispwordstart(ch)) {
				classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, styler);
				state = SCE_LISP_DEFAULT;
			} /*else*/
			if (isLispoperator(ch) || ch=='\'') {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LISP_OPERATOR);
			}

		} else {
			if (state == SCE_LISP_COMMENT) {
				if (atEOL) {
					styler.ColourTo(i - 1, state);
					state = SCE_LISP_DEFAULT;
				}
			} else if (state == SCE_LISP_STRING) {
				if (ch == '\\') {
					if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
						i++;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\"') {
					styler.ColourTo(i, state);
					state = SCE_LISP_DEFAULT;
				}
			}
		}

	}
	styler.ColourTo(lengthDoc - 1, state);
}

static void FoldLispDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                            Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_LISP_OPERATOR) {
			if (ch == '(') {
				levelCurrent++;
			} else if (ch == ')') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const lispWordListDesc[] = {
	"Keywords",
	0
};

LexerModule lmLISP(SCLEX_LISP, ColouriseLispDoc, "lisp", FoldLispDoc, lispWordListDesc);
<commit_msg>Patch from Michael Goffioul to Lisp adds SYMBOL, SPECIAL, and MULTI_COMMENT states and a second keyword set.<commit_after>// Scintilla source code edit control
/** @file LexLisp.cxx
 ** Lexer for Lisp.
 ** Written by Alexey Yutkin.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"
#include "StyleContext.h"

#define SCE_LISP_CHARACTER 29
#define SCE_LISP_MACRO 30
#define SCE_LISP_MACRO_DISPATCH 31

static inline bool isLispoperator(char ch) {
	if (isascii(ch) && isalnum(ch))
		return false;
	if (ch == '\'' || ch == '`' || ch == '(' || ch == ')' )
		return true;
	return false;
}

static inline bool isLispwordstart(char ch) {
	return isascii(ch) && ch != ';'  && !isspacechar(ch) && !isLispoperator(ch) &&
		ch != '\n' && ch != '\r' &&  ch != '\"';
}

static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, WordList &keywords_kw, Accessor &styler) {
	PLATFORM_ASSERT(end >= start);
	char s[100];
	unsigned int i;
	bool digit_flag = true;
	for (i = 0; (i < end - start + 1) && (i < 99); i++) {
		s[i] = styler[start + i];
		s[i + 1] = '\0';
		if (!isdigit(s[i]) && (s[i] != '.')) digit_flag = false;
	}
	char chAttr = SCE_LISP_IDENTIFIER;

	if(digit_flag) chAttr = SCE_LISP_NUMBER;
	else {
		if (keywords.InList(s)) {
			chAttr = SCE_LISP_KEYWORD;
		} else if (keywords_kw.InList(s)) {
			chAttr = SCE_LISP_KEYWORD_KW;
		} else if ((s[0] == '*' && s[i-1] == '*') ||
			   (s[0] == '+' && s[i-1] == '+')) {
			chAttr = SCE_LISP_SPECIAL;
		}
	}
	styler.ColourTo(end, chAttr);
	return;
}

static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords_kw = *keywordlists[1];

	styler.StartAt(startPos);

	int state = initStyle, radix = -1;
	char chNext = styler[startPos];
	unsigned int lengthDoc = startPos + length;
	styler.StartSegment(startPos);
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			i += 1;
			continue;
		}

		if (state == SCE_LISP_DEFAULT) {
			if (ch == '#') {
				styler.ColourTo(i - 1, state);
				radix = -1;
				state = SCE_LISP_MACRO_DISPATCH;
			} else if (isLispwordstart(ch)) {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_IDENTIFIER;
			}
			else if (ch == ';') {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_COMMENT;
			}
			else if (isLispoperator(ch) || ch=='\'') {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LISP_OPERATOR);
				if (ch=='\'' && isLispwordstart(chNext)) {
					state = SCE_LISP_SYMBOL;
				}
			}
			else if (ch == '\"') {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_STRING;
			}
		} else if (state == SCE_LISP_IDENTIFIER || state == SCE_LISP_SYMBOL) {
			if (!isLispwordstart(ch)) {
				if (state == SCE_LISP_IDENTIFIER) {
					classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, keywords_kw, styler);
				} else {
					styler.ColourTo(i - 1, state);
				}
				state = SCE_LISP_DEFAULT;
			} /*else*/
			if (isLispoperator(ch) || ch=='\'') {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LISP_OPERATOR);
				if (ch=='\'' && isLispwordstart(chNext)) {
					state = SCE_LISP_SYMBOL;
				}
			}
		} else if (state == SCE_LISP_MACRO_DISPATCH) {
			if (!isdigit(ch)) {
				if (ch != 'r' && ch != 'R' && (i - styler.GetStartSegment()) > 1) {
					state = SCE_LISP_DEFAULT;
				} else {
					switch (ch) {
						case '|': state = SCE_LISP_MULTI_COMMENT; break;
						case 'o':
						case 'O': radix = 8; state = SCE_LISP_MACRO; break;
						case 'x':
						case 'X': radix = 16; state = SCE_LISP_MACRO; break;
						case 'b':
						case 'B': radix = 2; state = SCE_LISP_MACRO; break;
						case '\\': state = SCE_LISP_CHARACTER; break;
						case ':':
						case '-':
						case '+': state = SCE_LISP_MACRO; break;
						case '\'': if (isLispwordstart(chNext)) {
								   state = SCE_LISP_SPECIAL;
							   } else {
								   styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
								   styler.ColourTo(i, SCE_LISP_OPERATOR);
								   state = SCE_LISP_DEFAULT;
							   }
							   break;
						default: if (isLispoperator(ch)) {
								 styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
								 styler.ColourTo(i, SCE_LISP_OPERATOR);
							 }
							 state = SCE_LISP_DEFAULT;
							 break;
					}
				}
			}
		} else if (state == SCE_LISP_MACRO) {
			if (isLispwordstart(ch) && (radix == -1 || IsADigit(ch, radix))) {
				state = SCE_LISP_SPECIAL;
			} else {
				state = SCE_LISP_DEFAULT;
			}
		} else if (state == SCE_LISP_CHARACTER) {
			if (isLispoperator(ch)) {
				styler.ColourTo(i, SCE_LISP_SPECIAL);
				state = SCE_LISP_DEFAULT;
			} else if (isLispwordstart(ch)) {
				styler.ColourTo(i, SCE_LISP_SPECIAL);
				state = SCE_LISP_SPECIAL;
			} else {
				state = SCE_LISP_DEFAULT;
			}
		} else if (state == SCE_LISP_SPECIAL) {
			if (!isLispwordstart(ch) || (radix != -1 && !IsADigit(ch, radix))) {
				styler.ColourTo(i - 1, state);
				state = SCE_LISP_DEFAULT;
			}
			if (isLispoperator(ch) || ch=='\'') {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LISP_OPERATOR);
				if (ch=='\'' && isLispwordstart(chNext)) {
					state = SCE_LISP_SYMBOL;
				}
			}
		} else {
			if (state == SCE_LISP_COMMENT) {
				if (atEOL) {
					styler.ColourTo(i - 1, state);
					state = SCE_LISP_DEFAULT;
				}
			} else if (state == SCE_LISP_MULTI_COMMENT) {
				if (ch == '|' && chNext == '#') {
					i++;
					chNext = styler.SafeGetCharAt(i + 1);
					styler.ColourTo(i, state);
					state = SCE_LISP_DEFAULT;
				}
			} else if (state == SCE_LISP_STRING) {
				if (ch == '\\') {
					if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
						i++;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\"') {
					styler.ColourTo(i, state);
					state = SCE_LISP_DEFAULT;
				}
			}
		}

	}
	styler.ColourTo(lengthDoc - 1, state);
}

static void FoldLispDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                            Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_LISP_OPERATOR) {
			if (ch == '(') {
				levelCurrent++;
			} else if (ch == ')') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const lispWordListDesc[] = {
	"Functions and special operators",
	"Keywords",
	0
};

LexerModule lmLISP(SCLEX_LISP, ColouriseLispDoc, "lisp", FoldLispDoc, lispWordListDesc);
<|endoftext|>


<commit_before>// Copyright 2016-2017, Pavel Korozevtsev.

#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <unistd.h>

#include <cstdio>
#include <cstring>

#include <algorithm>
#include <memory>
#include <utility>
#include <vector>

#include "include/log.hpp"
#include "include/socket.hpp"
#include "include/utils.hpp"

namespace pkr {

int set_nonblock(int fd) {
    int flags = 1;
#ifdef O_NONBLOCK
    if ((flags = fcntl(fd, F_GETFL, 0)) == -1) {
        flags = 0;
    }
    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
#else
    return ioctl(fd, FIOBIO, &flags);
#endif
}

DescriptorRef::DescriptorRef(const FileDescriptor& fd)
    : Handler{fd.handler} {}

DescriptorHolder::DescriptorHolder(DescriptorHolder&& other)
    : Handler{std::move(other.handler)} {
    other.handler = -1;
}

DescriptorHolder::DescriptorHolder(int h)
    : Handler{h} {}

FileDescriptor::FileDescriptor(int h)
    : Handler{h} {
    if (handler < 0) {
        log.error("Invalid fildes");
    } else {
        set_nonblock(handler);
    }
}

FileDescriptor::FileDescriptor(FileDescriptor&& other)
    : Handler{std::move(other.handler)} {
    other.handler = -1;
}

FileDescriptor::FileDescriptor(DescriptorHolder&& other)
    : Handler{std::move(other.handler)} {
    other.handler = -1;
}

FileDescriptor::~FileDescriptor() {
    if (handler != -1) {
        close(handler);
    }
}

ssize_t FileDescriptor::read(char* dest, ssize_t nbyte) {
    ssize_t sz = 0;
    ssize_t len;
    do {
        len = ::read(handler, dest + sz, nbyte - sz);
        if (len > 0) {
            sz += len;
        }
    } while (sz < nbyte && len > 0);
    return sz;
}

ssize_t FileDescriptor::write(const char* buf, ssize_t nbyte) {
    ssize_t sz = 0;
    ssize_t len;
    do {
        len = ::write(handler, buf + sz, nbyte - sz);
        if (len > 0) {
            sz += len;
        }
    } while (sz < nbyte && len > 0);
    return sz;
}

std::string read(FileDescriptor& fd, size_t nbyte) {
    std::vector<char> buf(nbyte);
    const auto len = fd.read(buf.data(), nbyte);
    if (len <= 0) {
        log.message("Unable to read from socket");
    }
    return {buf.data(), buf.data() + len};
}

ssize_t write(FileDescriptor& fd, string_view buf) {
    return fd.write(buf.data(), buf.size());
}

DescriptorHolder make_server_socket(Port port) {
    DescriptorHolder serv(socket(AF_INET, SOCK_STREAM, 0));
    sockaddr_in address;
    address.sin_addr.s_addr = htonl(INADDR_ANY);
    address.sin_family = AF_INET;
    address.sin_port = htons(port);
    auto try_bind = [&address, &serv] {
        return bind(serv.handler, reinterpret_cast<const sockaddr*>(&address),
                    sizeof(address)) == 0;
    };
    enum { tries = 8 };
    for (int i = 0; i < tries && !try_bind(); ++i) {
        log.message("Unable to create server socket on port " +
                    std::to_string(port) + " (bind failed): " +
                    Logger::errstr());
        address.sin_port = htons(++port);
    }
    if (listen(serv.handler, SOMAXCONN) < 0) {
        log.fatal_error("Unable to create server socket (listen failed): " +
                        Logger::errstr());
    } else {
        log.print("Server socket was bound to port " + std::to_string(port));
    }
    return serv;
}

int accept_client_helper(int serv_sock_fd) {
    sockaddr_in client_address;
    socklen_t client_address_size = sizeof(client_address);
    const auto new_client_handler =
        ::accept(serv_sock_fd, reinterpret_cast<sockaddr*>(&client_address),
                 &client_address_size);
    if (new_client_handler >= 0) {
        char ip[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &client_address.sin_addr, ip, sizeof(ip));
        log.access(ip, ntohs(client_address.sin_port));
    }
    return new_client_handler;
}

DescriptorHolder accept_client(DescriptorRef serv_sock) {
    return {accept_client_helper(serv_sock.handler)};
}

ssize_t write_failure(Socket& cls, int status, string_view msg) {
    char headers[256];
    snprintf(headers, sizeof(headers), "HTTP/1.0 %d %s\r\n", status,
             msg.to_string().c_str());
    return write(cls, {headers, strlen(headers)});
}

ssize_t write_response(Socket& cls, int status, size_t file_size) {
    char headers[256];
    snprintf(headers, sizeof(headers),
             "HTTP/1.0 %d OK\r\n"
             "Content-Length: %lu\r\n"
             "\r\n",
             status, file_size);
    return write(cls, {headers, strlen(headers)});
}

}  // namespace pkr
<commit_msg>%lu -> %zu for size_t<commit_after>// Copyright 2016-2017, Pavel Korozevtsev.

#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <unistd.h>

#include <cstdio>
#include <cstring>

#include <algorithm>
#include <memory>
#include <utility>
#include <vector>

#include "include/log.hpp"
#include "include/socket.hpp"
#include "include/utils.hpp"

namespace pkr {

int set_nonblock(int fd) {
    int flags = 1;
#ifdef O_NONBLOCK
    if ((flags = fcntl(fd, F_GETFL, 0)) == -1) {
        flags = 0;
    }
    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
#else
    return ioctl(fd, FIOBIO, &flags);
#endif
}

DescriptorRef::DescriptorRef(const FileDescriptor& fd)
    : Handler{fd.handler} {}

DescriptorHolder::DescriptorHolder(DescriptorHolder&& other)
    : Handler{std::move(other.handler)} {
    other.handler = -1;
}

DescriptorHolder::DescriptorHolder(int h)
    : Handler{h} {}

FileDescriptor::FileDescriptor(int h)
    : Handler{h} {
    if (handler < 0) {
        log.error("Invalid fildes");
    } else {
        set_nonblock(handler);
    }
}

FileDescriptor::FileDescriptor(FileDescriptor&& other)
    : Handler{std::move(other.handler)} {
    other.handler = -1;
}

FileDescriptor::FileDescriptor(DescriptorHolder&& other)
    : Handler{std::move(other.handler)} {
    other.handler = -1;
}

FileDescriptor::~FileDescriptor() {
    if (handler != -1) {
        close(handler);
    }
}

ssize_t FileDescriptor::read(char* dest, ssize_t nbyte) {
    ssize_t sz = 0;
    ssize_t len;
    do {
        len = ::read(handler, dest + sz, nbyte - sz);
        if (len > 0) {
            sz += len;
        }
    } while (sz < nbyte && len > 0);
    return sz;
}

ssize_t FileDescriptor::write(const char* buf, ssize_t nbyte) {
    ssize_t sz = 0;
    ssize_t len;
    do {
        len = ::write(handler, buf + sz, nbyte - sz);
        if (len > 0) {
            sz += len;
        }
    } while (sz < nbyte && len > 0);
    return sz;
}

std::string read(FileDescriptor& fd, size_t nbyte) {
    std::vector<char> buf(nbyte);
    const auto len = fd.read(buf.data(), nbyte);
    if (len <= 0) {
        log.message("Unable to read from socket");
    }
    return {buf.data(), buf.data() + len};
}

ssize_t write(FileDescriptor& fd, string_view buf) {
    return fd.write(buf.data(), buf.size());
}

DescriptorHolder make_server_socket(Port port) {
    DescriptorHolder serv(socket(AF_INET, SOCK_STREAM, 0));
    sockaddr_in address;
    address.sin_addr.s_addr = htonl(INADDR_ANY);
    address.sin_family = AF_INET;
    address.sin_port = htons(port);
    auto try_bind = [&address, &serv] {
        return bind(serv.handler, reinterpret_cast<const sockaddr*>(&address),
                    sizeof(address)) == 0;
    };
    enum { tries = 8 };
    for (int i = 0; i < tries && !try_bind(); ++i) {
        log.message("Unable to create server socket on port " +
                    std::to_string(port) + " (bind failed): " +
                    Logger::errstr());
        address.sin_port = htons(++port);
    }
    if (listen(serv.handler, SOMAXCONN) < 0) {
        log.fatal_error("Unable to create server socket (listen failed): " +
                        Logger::errstr());
    } else {
        log.print("Server socket was bound to port " + std::to_string(port));
    }
    return serv;
}

int accept_client_helper(int serv_sock_fd) {
    sockaddr_in client_address;
    socklen_t client_address_size = sizeof(client_address);
    const auto new_client_handler =
        ::accept(serv_sock_fd, reinterpret_cast<sockaddr*>(&client_address),
                 &client_address_size);
    if (new_client_handler >= 0) {
        char ip[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &client_address.sin_addr, ip, sizeof(ip));
        log.access(ip, ntohs(client_address.sin_port));
    }
    return new_client_handler;
}

DescriptorHolder accept_client(DescriptorRef serv_sock) {
    return {accept_client_helper(serv_sock.handler)};
}

ssize_t write_failure(Socket& cls, int status, string_view msg) {
    char headers[256];
    snprintf(headers, sizeof(headers), "HTTP/1.0 %d %s\r\n", status,
             msg.to_string().c_str());
    return write(cls, {headers, strlen(headers)});
}

ssize_t write_response(Socket& cls, int status, size_t file_size) {
    char headers[256];
    snprintf(headers, sizeof(headers),
             "HTTP/1.0 %d OK\r\n"
             "Content-Length: %zu\r\n"
             "\r\n",
             status, file_size);
    return write(cls, {headers, strlen(headers)});
}

}  // namespace pkr
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main(int argc, char const *argv[]) {

	return 0;
}
<commit_msg>adding<commit_after>#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#define MX 3001
using namespace std;
std::vector<int> G[MX];
int main(int argc, char const *argv[]) {
	int n,m;
	cin>>n>>m;
	for(int i=0;i<m;i++){
		int x,y;
		cin>>x>>y;
		G[x].push_back(y);
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(i==j) continue;
			for(int k=0;k<G[i].size();k++){
				if(G[i][k]!= &&)
			}
		}
	}
	return 0;
}
<|endoftext|>


<commit_before>#include "dsa_common.h"

#include "console_logger.h"

#include <iostream>
#include <memory>
#include "util/date_time.h"

namespace dsa {

void ConsoleLogger::write_meta(std::ostream& stream, const char* level) {
  const string_& ts = DateTime::get_ts();
  // use a substring of the timestamp
  stream << '[' << level << string_(&ts[5], &ts[23]) << "]  ";
}

void ConsoleLogger::log(const string_& str, uint8_t lvl) {
  if ((lvl & filter) || level == Logger::ALL___) {
    std::cout << str;
    std::cout.flush();
  }
}
}
<commit_msg>keep year in the logger timestamp<commit_after>#include "dsa_common.h"

#include "console_logger.h"

#include <iostream>
#include <memory>
#include "util/date_time.h"

namespace dsa {

void ConsoleLogger::write_meta(std::ostream& stream, const char* level) {
  const string_& ts = DateTime::get_ts();
  // use a substring of the timestamp
  stream << '[' << level << string_(&ts[0], &ts[23]) << "]  ";
}

void ConsoleLogger::log(const string_& str, uint8_t lvl) {
  if ((lvl & filter) || level == Logger::ALL___) {
    std::cout << str;
    std::cout.flush();
  }
}
}
<|endoftext|>


<commit_before>// Alexis Giraudet
// Théo Cesbron

#ifndef HASH_TABLE_HPP
#define HASH_TABLE_HPP

#include <functional>
#include "map.hpp"

/**
 * Classe hash_table: table de hachage
 * Implémentation avec tableau de dictionnaires.
**/
template <typename K, typename V, int S>
class hash_table
{
    private:
        map<K,V> *_dictionaries;
        std::hash<K> _hash_fn;

    public:
        hash_table();
        ~hash_table();
        void clear();
        bool contains_key(const K& key) const;
        bool contains_value(const V& value) const;
        V get(const K& key) const;
        V& get_ref(const K& key) const;
        bool is_empty() const;
        K* keys_array() const;
        std::ostream& print() const;
        std::ostream& print(std::ostream& os) const;
        bool put(const K& key, const V& value);
        bool remove(const K& key);
        int size() const;
        void to_list(std::list< std::pair<K,V> >& ls) const;
        V* values_array() const;
};

template <typename K, typename V, int S>
hash_table<K,V,S>::hash_table(): _dictionaries(0)
{
    _dictionaries = new map<K,V>[S];
}

template <typename K, typename V, int S>
hash_table<K,V,S>::~hash_table()
{
    delete[] _dictionaries;
}

/**
 * Vide la table de hachage.
 * O(n)
**/
template <typename K, typename V, int S>
void hash_table<K,V,S>::clear()
{
    for(int i=0; i<S; i++)
    {
        _dictionaries[i].clear();
    }
}

/**
 * Retourne vrai si la table de hachage contient la clef key, retourne faux dans le cas contraire.
 * O(n)
**/
template <typename K, typename V, int S>
bool hash_table<K,V,S>::contains_key(const K& key) const
{
    size_t i = _hash_fn(key)%S;
    return _dictionaries[i].contains_key(key);
}

/**
 * Retourne vrai si la table de hachage contient la valeur value, retourne faux dans le cas contraire.
 * O(n)
**/
template <typename K, typename V, int S>
bool hash_table<K,V,S>::contains_value(const V& value) const
{
    for(int i=0; i<S; i++)
    {
        if(_dictionaries[i].contains_value(value))
        {
            return true;
        }
    }
    return false;
}

/**
 * Retourne la valeur associée à la clef key si la table de hachage contient la clef key, lève une exception dans le cas contraire.
 * O(n)
**/
template <typename K, typename V, int S>
V hash_table<K,V,S>::get(const K& key) const
{
    size_t i = _hash_fn(key)%S;
    return _dictionaries[i].get(key);
}

/**
 * Retourne la référence de la valeur associée à la clef key si la table de hachage contient la clef key, lève une exception dans le cas contraire.
 * O(n)
**/
template <typename K, typename V, int S>
V& hash_table<K,V,S>::get_ref(const K& key) const
{
    size_t i = _hash_fn(key)%S;
    return _dictionaries[i].get(key);
}

/**
 * Retourne vrai si la table de hachage est vide, retourne faux dans le cas contraire.
 * O(1)
**/
template <typename K, typename V, int S>
bool hash_table<K,V,S>::is_empty() const
{
    for(int i=0; i<S; i++)
    {
        if(!_dictionaries[i].is_empty())
        {
            return false;
        }
    }
    return true;
}

/**
 * Retourne un tableau contenant toutes les clefs de la table de hachage.
 * O(n)
**/
template <typename K, typename V, int S>
K* hash_table<K,V,S>::keys_array() const
{
    K *res = new K[size()];
    int i=0;
    for(int j=0; j<S; j++)
    {
        K *tmp = _dictionaries[j].keys_array();
        for(int k=0; k<_dictionaries[j].size(); k++)
        {
            res[i] = tmp[k];
            i++;
        }
        delete[] tmp;
    }
    return res;
}

/**
 * Affiche la table de hachage sur la sortie standard.
 * O(n)
**/
template <typename K, typename V, int S>
std::ostream& hash_table<K,V,S>::print() const
{
    return print(std::cout);
}

/**
 * Affiche la table de hachage sur la sortie os.
 * O(n)
**/
template <typename K, typename V, int S>
std::ostream& hash_table<K,V,S>::print(std::ostream& os) const
{
    for(int i=0; i<S; i++)
    {
        os << _dictionaries[i];
    }
    return os;
}

/**
 * Ajoute un nouveau couple clef/valeur a la table de hachage si celle-ci ne contient pas la clef key, si la table de hachage contient la clef key alors la valeur associée à la clef sera remplacée par value.
 * O(n)
**/
template <typename K, typename V, int S>
bool hash_table<K,V,S>::put(const K& key, const V& value)
{
    size_t i = _hash_fn(key)%S;
    return _dictionaries[i].put(key,value);
}

/**
 * Supprime le couple clef/valeur associé à la clef key de la table de hachage.
 * O(n)
**/
template <typename K, typename V, int S>
bool hash_table<K,V,S>::remove(const K& key)
{
    size_t i = _hash_fn(key)%S;
    return _dictionaries[i].remove(key);
}

/**
 * Retourne la taille de la table de hachage.
 *
**/
template <typename K, typename V, int S>
int hash_table<K,V,S>::size() const
{
    int res=0;
    for(int i=0; i<S; i++)
    {
        res += _dictionaries[i].size();
    }
    return res;
}

template <typename K, typename V, int S>
void hash_table<K,V,S>::to_list(std::list< std::pair<K,V> >& ls) const
{
    for(int i=0; i<S; i++)
    {
        _dictionaries[i].to_list(ls);
    }
}

/**
 * Retourne un tableau contenant toutes les valeurs de la table de hachage.
 * O(n)
**/
template <typename K, typename V, int S>
V* hash_table<K,V,S>::values_array() const
{
    V *res = new V[size()];
    int i=0;
    for(int j=0; j<S; j++)
    {
        V *tmp = _dictionaries[j].values_array();
        for(int k=0; k<_dictionaries[j].size(); k++)
        {
            res[i] = tmp[k];
            i++;
        }
        delete[] tmp;
    }
    return res;
}

/**
 * Définition de l'opérateur << pour gérer les flux.
**/
template <typename K, typename V, int S>
std::ostream& operator<<(std::ostream& os, const hash_table<K,V,S>& m)
{
    return m.print(os);
}

#endif
<commit_msg>add doxigen and clear code<commit_after>/*!
 * \file hash_table.hpp
 * \brief Classe hash_table
 * \author Alexis Giraudet
 * \author Théo Cesbron
 * \version 1.0
 * \date 18 avril 2014
 */

#ifndef HASH_TABLE_HPP
#define HASH_TABLE_HPP

#include <functional>
#include "map.hpp"

/*!
 * \class map
 * \brief Implémentation générique d'une table de hachage avec taleaux associatifs. K le type des clefs, V le type des valeurs et S le nombre de maps.
 */
template <typename K, typename V, int S>
class hash_table
{
    private:
        map<K,V>* _data;
        std::hash<K> _hash_fn;

    public:
        /*!
         * \brief Constructeur. O(1)
         */
        hash_table();

        /*!
         * \brief Destructeur. O(n)
         */
        ~hash_table();

        /*!
         * \brief Vide la hash_table. O(n)
         */
        void clear();

        /*!
         * \brief Retourne vrai si la hash_table contient la clef key, retourne faux dans le cas contraire. O(n)
         * \param key : la clef recherchée
         * \return vrai si la hash_table contient la clef key, sinon faux
         */
        bool contains_key(const K& key) const;

        /*!
         * \brief Retourne vrai si la hash_table contient la valeur value, retourne faux dans le cas contraire. O(n)
         * \param value : la valeur recherchée
         * \return vrai si la hash_table contient la valeur value, sinon faux
         */
        bool contains_value(const V& value) const;

        /*!
         * \brief Retourne la valeur associée à la clef key si la hash_table contient la clef key, lève une exception dans le cas contraire. O(n)
         * \param key : la clef
         * \return la valeur associée à la clef key
         */
        V get(const K& key) const;

        /*!
         * \brief Retourne la référence de la valeur associée à la clef key si la hash_table contient la clef key, lève une exception dans le cas contraire. O(n)
         * \param key : la clef
         * \return la référence de la valeur associée à la clef key
         */
        V& get_ref(const K& key) const;

        /*!
         * \brief Retourne vrai si la hash_table est vide, retourne faux dans le cas contraire. O(1)
         * \return vrai si la hash_table est vide, sinon faux
         */
        bool is_empty() const;

        /*!
         * \deprecated utiliser to_list()
         * \brief Retourne un tableau contenant toutes les clefs de la hash_table. O(n)
         * \return le tableau des clefs
         */
        K* keys_array() const;

        /*!
         * \brief Ajoute un nouveau couple clef-valeur à la hash_table si celle-ci ne contient pas la clef key, si la hash_table contient la clef key alors la valeur associée à la clef sera remplacée par value. O(n)
         * \param key : la clef
         * \param value : la valeur associée à la clef
         * \return vrai si la clef n'était pas présente, sinon faux (la valeur précédente a été écrasée)
         */
        bool put(const K& key, const V& value);

        /*!
         * \brief Supprime le couple clef-valeur associé à la clef key de la hash_table. O(n)
         * \param key : la clef à supprimer
         * \return vrai si la clef et la valeur associée ont bien été supprimé, sinon faux
         */
        bool remove(const K& key);

        /*!
         * \brief Retourne la taille de la hash_table. O(1)
         * \return la taille (le nombre de couples clef-valeur)
         */
        int size() const;

        /*!
         * \brief Charge les élément de la hash_table dans la liste passée en paramètre. O(n)
         * \param ls : la liste où charger les couples clef-valeur
         */
        void to_list(std::list<std::pair<K,V> >& ls) const;

        /*!
         * \deprecated Utiliser to_list()
         * \brief Retourne un tableau contenant toutes les valeurs de la hash_table. O(n)
         * \return le tableau des valeurs
         */
        V* values_array() const;
};

template <typename K, typename V, int S>
hash_table<K,V,S>::hash_table(): _data(0)
{
    _data = new map<K,V>[S];
}

template <typename K, typename V, int S>
hash_table<K,V,S>::~hash_table()
{
    delete[] _data;
}

template <typename K, typename V, int S>
void hash_table<K,V,S>::clear()
{
    for(int i=0; i<S; i++)
    {
        _data[i].clear();
    }
}

template <typename K, typename V, int S>
bool hash_table<K,V,S>::contains_key(const K& key) const
{
    return _data[_hash_fn(key)%S].contains_key(key);
}

template <typename K, typename V, int S>
bool hash_table<K,V,S>::contains_value(const V& value) const
{
    for(int i=0; i<S; i++)
    {
        if(_data[i].contains_value(value))
        {
            return true;
        }
    }
    return false;
}

template <typename K, typename V, int S>
V hash_table<K,V,S>::get(const K& key) const
{
    return _data[_hash_fn(key)%S].get(key);
}

template <typename K, typename V, int S>
V& hash_table<K,V,S>::get_ref(const K& key) const
{
    return _data[_hash_fn(key)%S].get(key);
}

template <typename K, typename V, int S>
bool hash_table<K,V,S>::is_empty() const
{
    for(int i=0; i<S; i++)
    {
        if(!_data[i].is_empty())
        {
            return false;
        }
    }
    return true;
}

template <typename K, typename V, int S>
K* hash_table<K,V,S>::keys_array() const
{
    K *res = new K[size()];
    int i=0;
    for(int j=0; j<S; j++)
    {
        K *tmp = _data[j].keys_array();
        for(int k=0; k<_data[j].size(); k++)
        {
            res[i] = tmp[k];
            i++;
        }
        delete[] tmp;
    }
    return res;
}

template <typename K, typename V, int S>
bool hash_table<K,V,S>::put(const K& key, const V& value)
{
    return _data[_hash_fn(key)%S].put(key,value);
}

template <typename K, typename V, int S>
bool hash_table<K,V,S>::remove(const K& key)
{
    return _data[_hash_fn(key)%S].remove(key);
}

template <typename K, typename V, int S>
int hash_table<K,V,S>::size() const
{
    int res=0;
    for(int i=0; i<S; i++)
    {
        res += _data[i].size();
    }
    return res;
}

template <typename K, typename V, int S>
void hash_table<K,V,S>::to_list(std::list<std::pair<K,V> >& ls) const
{
    for(int i=0; i<S; i++)
    {
        _data[i].to_list(ls);
    }
}

template <typename K, typename V, int S>
V* hash_table<K,V,S>::values_array() const
{
    V *res = new V[size()];
    int i=0;
    for(int j=0; j<S; j++)
    {
        V *tmp = _data[j].values_array();
        for(int k=0; k<_data[j].size(); k++)
        {
            res[i] = tmp[k];
            i++;
        }
        delete[] tmp;
    }
    return res;
}

/*!
 * \brief Surchage de l'opérateur de flux pour afficher la map. O(n)
 * \param os : le flux de sortie
 * \param m : la map à afficher
 * \return le flux de sortie
 */
template <typename K, typename V, int S>
std::ostream& operator<<(std::ostream& os, const hash_table<K,V,S>& ht)
{
    std::list<std::pair<K,V> > ls;
    ht.to_list(ls);
    for(typename std::list<std::pair<K,V> >::iterator it=ls.begin(); it != ls.end(); it++)
    {
        os << (*it).first << " : " << (*it).second << std::endl;
    }
    return os;
}

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <nix/hdf5/Group.hpp>

#include <nix/util/util.hpp>

#include <nix/hdf5/ExceptionHDF5.hpp>
#include <nix/hdf5/hdf5include.hpp>

namespace nix {
namespace hdf5 {

optGroup::optGroup(const Group &parent, const std::string &g_name)
    : parent(parent), g_name(g_name)
{}

boost::optional<Group> optGroup::operator() (bool create) const {
    if (parent.hasGroup(g_name)) {
        g = boost::optional<Group>(parent.openGroup(g_name));
    } else if (create) {
        g = boost::optional<Group>(parent.openGroup(g_name, true));
    }
    return g;
}

Group::Group() : LocID() {}

Group::Group(hid_t hid) : LocID(hid) {}

Group::Group(const Group &other) : LocID(other) {}

bool Group::hasObject(const std::string &name) const {
    // empty string should return false, not exception (which H5Lexists would)
    if (name.empty()) {
        return false;
    }

    HTri res = H5Lexists(hid, name.c_str(), H5P_DEFAULT);
    return res.check("Group::hasObject(): H5Lexists failed");
}

bool Group::objectOfType(const std::string &name, H5O_type_t type) const {
    H5O_info_t info;

    hid_t obj = H5Oopen(hid, name.c_str(), H5P_DEFAULT);

    if (!H5Iis_valid(obj)) {
        return false;
    }

    HErr err = H5Oget_info(obj, &info);
    err.check("Could not obtain object info");

    bool res = info.type == type;

    H5Oclose(obj);
    return res;
}

size_t Group::objectCount() const {
    hsize_t n_objs;
    HErr res = H5Gget_num_objs(hid, &n_objs);
    res.check("Could not get object count");
    return n_objs;
}

boost::optional<Group> Group::findGroupByAttribute(const std::string &attribute, const std::string &value) const {
    boost::optional<Group> ret;

    // look up first direct sub-group that has given attribute with given value
    for (size_t index = 0; index < objectCount(); index++) {
        std::string obj_name = objectName(index);
        if(hasGroup(obj_name)) {
            Group group = openGroup(obj_name, false);
            if(group.hasAttr(attribute)) {
                std::string attr_value;
                group.getAttr(attribute, attr_value);
                if (attr_value == value) {
                    ret = group;
                    break;
                }
            }
        }
    }

    return ret;
}

boost::optional<DataSet> Group::findDataByAttribute(const std::string &attribute, const std::string &value) const {
    std::vector<DataSet> dsets;
    boost::optional<DataSet> ret;

    // look up all direct sub-datasets that have the given attribute
    for (size_t index = 0; index < objectCount(); index++) {
        std::string obj_name = objectName(index);
        if(hasData(obj_name)) {
            DataSet ds = openData(obj_name);

            if (ds.hasAttr(attribute)) {
                dsets.push_back(ds);
            }
        }
    }
    // look for first dataset with given attribute set to given value
    auto found = std::find_if(dsets.begin(), dsets.end(),
                 [value, attribute](DataSet &dset) {
                     std::string attr_value;
                     dset.getAttr(attribute, attr_value);
                     return attr_value == value; });
    if(found != dsets.end()) ret = *found;

    return ret;
}

std::string Group::objectName(size_t index) const {
    // check if index valid
    if(index > objectCount()) {
        throw OutOfBounds("No object at given index", index);
    }

    std::string str_name;
    // check whether name is found by index
    ssize_t name_len = H5Lget_name_by_idx(hid,
                                                  ".",
                                                  H5_INDEX_NAME,
                                                  H5_ITER_NATIVE,
                                                  (hsize_t) index,
                                                  NULL,
                                                  0,
                                                  H5P_DEFAULT);
    if (name_len > 0) {
        char* name = new char[name_len+1];
        name_len = H5Lget_name_by_idx(hid,
                                      ".",
                                      H5_INDEX_NAME,
                                      H5_ITER_NATIVE,
                                      (hsize_t) index,
                                      name,
                                      name_len+1,
                                      H5P_DEFAULT);
        str_name = name;
        delete [] name;
    } else {
        throw H5Exception("objectName: No object found, H5Lget_name_by_idx returned no name");
    }

    return str_name;
}

bool Group::hasData(const std::string &name) const {
    return hasObject(name) && objectOfType(name, H5O_TYPE_DATASET);
}

void Group::removeData(const std::string &name) {
    if (hasData(name)) {
        HErr res = H5Gunlink(hid, name.c_str());
        res.check("Group::removeData(): Could not unlink DataSet");
    }
}

DataSet Group::createData(const std::string &name,
        DataType dtype,
        const NDSize &size) const
{
    h5x::DataType fileType = data_type_to_h5_filetype(dtype);
    return createData(name, fileType, size);
}

DataSet Group::createData(const std::string &name,
        const h5x::DataType &fileType,
        const NDSize &size,
        const NDSize &maxsize,
        NDSize chunks,
        bool max_size_unlimited,
        bool guess_chunks) const
{
    DataSpace space;

    if (size) {
        if (maxsize) {
            space = DataSpace::create(size, maxsize);
        } else {
            space = DataSpace::create(size, max_size_unlimited);
        }
    }

    BaseHDF5 dcpl = H5Pcreate(H5P_DATASET_CREATE);
    dcpl.check("Could not create data creation plist");

    if (!chunks && guess_chunks) {
        chunks = DataSet::guessChunking(size, fileType.size());
    }

    if (chunks) {
        int rank = static_cast<int>(chunks.size());
        HErr res = H5Pset_chunk(dcpl.h5id(), rank, chunks.data());
        res.check("Could not set chunk size on data set creation plist");
    }

    DataSet ds = H5Dcreate(hid, name.c_str(), fileType.h5id(), space.h5id(), H5P_DEFAULT, dcpl.h5id(), H5P_DEFAULT);
    ds.check("Group::createData: Could not create DataSet with name " + name);

    return ds;
}

DataSet Group::openData(const std::string &name) const {
    DataSet ds = H5Dopen(hid, name.c_str(), H5P_DEFAULT);
    ds.check("Group::openData(): Could not open DataSet");
    return ds;
}

bool Group::hasGroup(const std::string &name) const {
    return hasObject(name) && objectOfType(name, H5O_TYPE_GROUP);
}

Group Group::openGroup(const std::string &name, bool create) const {
    if(!util::nameCheck(name)) throw InvalidName("openGroup");
    Group g;
    if (hasGroup(name)) {
        g = Group(H5Gopen(hid, name.c_str(), H5P_DEFAULT));
        g.check("Group::openGroup(): Could not open group: " + name);
    } else if (create) {
        hid_t gcpl = H5Pcreate(H5P_GROUP_CREATE);

        if (gcpl < 0) {
            throw H5Exception("Unable to create group with name '" + name + "'! (H5Pcreate)");
        }

        //we want hdf5 to keep track of the order in which links were created so that
        //the order for indexed based accessors is stable cf. issue #387
        HErr res = H5Pset_link_creation_order(gcpl, H5P_CRT_ORDER_TRACKED|H5P_CRT_ORDER_INDEXED);
        res.check("Unable to create group with name '" + name + "'! (H5Pset_link_cr...)");

        g = Group(H5Gcreate2(hid, name.c_str(), H5P_DEFAULT, gcpl, H5P_DEFAULT));
        H5Pclose(gcpl);
        g.check("Unable to create group with name '" + name + "'! (H5Gcreate2)");

    } else {
        throw H5Exception("Unable to open group with name '" + name + "'!");
    }
    return g;
}

optGroup Group::openOptGroup(const std::string &name) {
    if(!util::nameCheck(name)) throw InvalidName("openOptGroup");
    return optGroup(*this, name);
}

void Group::removeGroup(const std::string &name) {
    if (hasGroup(name))
        H5Gunlink(hid, name.c_str());
}

void Group::renameGroup(const std::string &old_name, const std::string &new_name) {
    if(!util::nameCheck(new_name)) throw InvalidName("renameGroup");
    if (hasGroup(old_name)) {
        H5Gmove(hid, old_name.c_str(), new_name.c_str()); //FIXME: H5Gmove is deprecated
    }
}

Group Group::createLink(const Group &target, const std::string &link_name) {
    if(!util::nameCheck(link_name)) throw InvalidName("createLink");
    HErr res = H5Lcreate_hard(target.hid, ".", hid, link_name.c_str(),
                              H5L_SAME_LOC, H5L_SAME_LOC);
    res.check("Unable to create link " + link_name);
    return openGroup(link_name, false);
}

// TODO implement some kind of roll-back in order to avoid half renamed links.
bool Group::renameAllLinks(const std::string &old_name, const std::string &new_name) {
    if(!util::nameCheck(new_name)) throw InvalidName("renameAllLinks");
    bool renamed = false;

    if (hasGroup(old_name)) {
        std::vector<std::string> links;

        Group  group     = openGroup(old_name, false);
        std::string gname = group.name();

        while (! gname.empty()) {
            deleteLink(gname);
            links.push_back(gname);
            gname = group.name();
        }

        renamed = links.size() > 0;
        for (std::string curr_name: links) {
            size_t pos = curr_name.find_last_of('/') + 1;

            if (curr_name.substr(pos) == old_name) {
                curr_name.replace(curr_name.begin() + pos, curr_name.end(), new_name.begin(), new_name.end());
            }

            HErr res = H5Lcreate_hard(group.hid, ".", hid, curr_name.c_str(),
                                      H5L_SAME_LOC, H5L_SAME_LOC);
            renamed = renamed && res;
        }
    }

    return renamed;
}

// TODO implement some kind of roll-back in order to avoid half removed links.
bool Group::removeAllLinks(const std::string &name) {
    bool removed = false;

    if (hasGroup(name)) {
        Group  group      = openGroup(name, false);

        std::string gname = group.name();

        while (! gname.empty()) {
            deleteLink(gname);
            gname = group.name();
        }

        removed = true;
    }

    return removed;
}

boost::optional<Group> Group::findGroupByNameOrAttribute(std::string const &attr, std::string const &value) const {

    if (hasObject(value)) {
        return boost::make_optional(openGroup(value, false));
    } else if (util::looksLikeUUID(value)) {
        return findGroupByAttribute(attr, value);
    } else {
        return boost::optional<Group>();
    }
}

boost::optional<DataSet> Group::findDataByNameOrAttribute(std::string const &attr, std::string const &value) const {

    if (hasObject(value)) {
        return boost::make_optional(openData(value));
    } else if (util::looksLikeUUID(value)) {
        return findDataByAttribute(attr, value);
    } else {
        return boost::optional<DataSet>();
    }
}

Group::~Group()
{}

} // namespace hdf5
} // namespace nix
<commit_msg>[h5x] Group::openGroup: use H5 C API for prop list<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <nix/hdf5/Group.hpp>

#include <nix/util/util.hpp>

#include <nix/hdf5/ExceptionHDF5.hpp>
#include <nix/hdf5/hdf5include.hpp>

namespace nix {
namespace hdf5 {

optGroup::optGroup(const Group &parent, const std::string &g_name)
    : parent(parent), g_name(g_name)
{}

boost::optional<Group> optGroup::operator() (bool create) const {
    if (parent.hasGroup(g_name)) {
        g = boost::optional<Group>(parent.openGroup(g_name));
    } else if (create) {
        g = boost::optional<Group>(parent.openGroup(g_name, true));
    }
    return g;
}

Group::Group() : LocID() {}

Group::Group(hid_t hid) : LocID(hid) {}

Group::Group(const Group &other) : LocID(other) {}

bool Group::hasObject(const std::string &name) const {
    // empty string should return false, not exception (which H5Lexists would)
    if (name.empty()) {
        return false;
    }

    HTri res = H5Lexists(hid, name.c_str(), H5P_DEFAULT);
    return res.check("Group::hasObject(): H5Lexists failed");
}

bool Group::objectOfType(const std::string &name, H5O_type_t type) const {
    H5O_info_t info;

    hid_t obj = H5Oopen(hid, name.c_str(), H5P_DEFAULT);

    if (!H5Iis_valid(obj)) {
        return false;
    }

    HErr err = H5Oget_info(obj, &info);
    err.check("Could not obtain object info");

    bool res = info.type == type;

    H5Oclose(obj);
    return res;
}

size_t Group::objectCount() const {
    hsize_t n_objs;
    HErr res = H5Gget_num_objs(hid, &n_objs);
    res.check("Could not get object count");
    return n_objs;
}

boost::optional<Group> Group::findGroupByAttribute(const std::string &attribute, const std::string &value) const {
    boost::optional<Group> ret;

    // look up first direct sub-group that has given attribute with given value
    for (size_t index = 0; index < objectCount(); index++) {
        std::string obj_name = objectName(index);
        if(hasGroup(obj_name)) {
            Group group = openGroup(obj_name, false);
            if(group.hasAttr(attribute)) {
                std::string attr_value;
                group.getAttr(attribute, attr_value);
                if (attr_value == value) {
                    ret = group;
                    break;
                }
            }
        }
    }

    return ret;
}

boost::optional<DataSet> Group::findDataByAttribute(const std::string &attribute, const std::string &value) const {
    std::vector<DataSet> dsets;
    boost::optional<DataSet> ret;

    // look up all direct sub-datasets that have the given attribute
    for (size_t index = 0; index < objectCount(); index++) {
        std::string obj_name = objectName(index);
        if(hasData(obj_name)) {
            DataSet ds = openData(obj_name);

            if (ds.hasAttr(attribute)) {
                dsets.push_back(ds);
            }
        }
    }
    // look for first dataset with given attribute set to given value
    auto found = std::find_if(dsets.begin(), dsets.end(),
                 [value, attribute](DataSet &dset) {
                     std::string attr_value;
                     dset.getAttr(attribute, attr_value);
                     return attr_value == value; });
    if(found != dsets.end()) ret = *found;

    return ret;
}

std::string Group::objectName(size_t index) const {
    // check if index valid
    if(index > objectCount()) {
        throw OutOfBounds("No object at given index", index);
    }

    std::string str_name;
    // check whether name is found by index
    ssize_t name_len = H5Lget_name_by_idx(hid,
                                                  ".",
                                                  H5_INDEX_NAME,
                                                  H5_ITER_NATIVE,
                                                  (hsize_t) index,
                                                  NULL,
                                                  0,
                                                  H5P_DEFAULT);
    if (name_len > 0) {
        char* name = new char[name_len+1];
        name_len = H5Lget_name_by_idx(hid,
                                      ".",
                                      H5_INDEX_NAME,
                                      H5_ITER_NATIVE,
                                      (hsize_t) index,
                                      name,
                                      name_len+1,
                                      H5P_DEFAULT);
        str_name = name;
        delete [] name;
    } else {
        throw H5Exception("objectName: No object found, H5Lget_name_by_idx returned no name");
    }

    return str_name;
}

bool Group::hasData(const std::string &name) const {
    return hasObject(name) && objectOfType(name, H5O_TYPE_DATASET);
}

void Group::removeData(const std::string &name) {
    if (hasData(name)) {
        HErr res = H5Gunlink(hid, name.c_str());
        res.check("Group::removeData(): Could not unlink DataSet");
    }
}

DataSet Group::createData(const std::string &name,
        DataType dtype,
        const NDSize &size) const
{
    h5x::DataType fileType = data_type_to_h5_filetype(dtype);
    return createData(name, fileType, size);
}

DataSet Group::createData(const std::string &name,
        const h5x::DataType &fileType,
        const NDSize &size,
        const NDSize &maxsize,
        NDSize chunks,
        bool max_size_unlimited,
        bool guess_chunks) const
{
    DataSpace space;

    if (size) {
        if (maxsize) {
            space = DataSpace::create(size, maxsize);
        } else {
            space = DataSpace::create(size, max_size_unlimited);
        }
    }

    BaseHDF5 dcpl = H5Pcreate(H5P_DATASET_CREATE);
    dcpl.check("Could not create data creation plist");

    if (!chunks && guess_chunks) {
        chunks = DataSet::guessChunking(size, fileType.size());
    }

    if (chunks) {
        int rank = static_cast<int>(chunks.size());
        HErr res = H5Pset_chunk(dcpl.h5id(), rank, chunks.data());
        res.check("Could not set chunk size on data set creation plist");
    }

    DataSet ds = H5Dcreate(hid, name.c_str(), fileType.h5id(), space.h5id(), H5P_DEFAULT, dcpl.h5id(), H5P_DEFAULT);
    ds.check("Group::createData: Could not create DataSet with name " + name);

    return ds;
}

DataSet Group::openData(const std::string &name) const {
    DataSet ds = H5Dopen(hid, name.c_str(), H5P_DEFAULT);
    ds.check("Group::openData(): Could not open DataSet");
    return ds;
}

bool Group::hasGroup(const std::string &name) const {
    return hasObject(name) && objectOfType(name, H5O_TYPE_GROUP);
}

Group Group::openGroup(const std::string &name, bool create) const {
    if(!util::nameCheck(name)) throw InvalidName("openGroup");
    Group g;

    if (hasGroup(name)) {
        g = Group(H5Gopen(hid, name.c_str(), H5P_DEFAULT));
        g.check("Group::openGroup(): Could not open group: " + name);
    } else if (create) {
        BaseHDF5 gcpl = H5Pcreate(H5P_GROUP_CREATE);
        gcpl.check("Unable to create group with name '" + name + "'! (H5Pcreate)");

        //we want hdf5 to keep track of the order in which links were created so that
        //the order for indexed based accessors is stable cf. issue #387
        HErr res = H5Pset_link_creation_order(gcpl.h5id(), H5P_CRT_ORDER_TRACKED|H5P_CRT_ORDER_INDEXED);
        res.check("Unable to create group with name '" + name + "'! (H5Pset_link_cr...)");

        g = Group(H5Gcreate2(hid, name.c_str(), H5P_DEFAULT, gcpl.h5id(), H5P_DEFAULT));
        g.check("Unable to create group with name '" + name + "'! (H5Gcreate2)");

    } else {
        throw H5Exception("Unable to open group with name '" + name + "'!");
    }

    return g;
}

optGroup Group::openOptGroup(const std::string &name) {
    if(!util::nameCheck(name)) throw InvalidName("openOptGroup");
    return optGroup(*this, name);
}

void Group::removeGroup(const std::string &name) {
    if (hasGroup(name))
        H5Gunlink(hid, name.c_str());
}

void Group::renameGroup(const std::string &old_name, const std::string &new_name) {
    if(!util::nameCheck(new_name)) throw InvalidName("renameGroup");
    if (hasGroup(old_name)) {
        H5Gmove(hid, old_name.c_str(), new_name.c_str()); //FIXME: H5Gmove is deprecated
    }
}

Group Group::createLink(const Group &target, const std::string &link_name) {
    if(!util::nameCheck(link_name)) throw InvalidName("createLink");
    HErr res = H5Lcreate_hard(target.hid, ".", hid, link_name.c_str(),
                              H5L_SAME_LOC, H5L_SAME_LOC);
    res.check("Unable to create link " + link_name);
    return openGroup(link_name, false);
}

// TODO implement some kind of roll-back in order to avoid half renamed links.
bool Group::renameAllLinks(const std::string &old_name, const std::string &new_name) {
    if(!util::nameCheck(new_name)) throw InvalidName("renameAllLinks");
    bool renamed = false;

    if (hasGroup(old_name)) {
        std::vector<std::string> links;

        Group  group     = openGroup(old_name, false);
        std::string gname = group.name();

        while (! gname.empty()) {
            deleteLink(gname);
            links.push_back(gname);
            gname = group.name();
        }

        renamed = links.size() > 0;
        for (std::string curr_name: links) {
            size_t pos = curr_name.find_last_of('/') + 1;

            if (curr_name.substr(pos) == old_name) {
                curr_name.replace(curr_name.begin() + pos, curr_name.end(), new_name.begin(), new_name.end());
            }

            HErr res = H5Lcreate_hard(group.hid, ".", hid, curr_name.c_str(),
                                      H5L_SAME_LOC, H5L_SAME_LOC);
            renamed = renamed && res;
        }
    }

    return renamed;
}

// TODO implement some kind of roll-back in order to avoid half removed links.
bool Group::removeAllLinks(const std::string &name) {
    bool removed = false;

    if (hasGroup(name)) {
        Group  group      = openGroup(name, false);

        std::string gname = group.name();

        while (! gname.empty()) {
            deleteLink(gname);
            gname = group.name();
        }

        removed = true;
    }

    return removed;
}

boost::optional<Group> Group::findGroupByNameOrAttribute(std::string const &attr, std::string const &value) const {

    if (hasObject(value)) {
        return boost::make_optional(openGroup(value, false));
    } else if (util::looksLikeUUID(value)) {
        return findGroupByAttribute(attr, value);
    } else {
        return boost::optional<Group>();
    }
}

boost::optional<DataSet> Group::findDataByNameOrAttribute(std::string const &attr, std::string const &value) const {

    if (hasObject(value)) {
        return boost::make_optional(openData(value));
    } else if (util::looksLikeUUID(value)) {
        return findDataByAttribute(attr, value);
    } else {
        return boost::optional<DataSet>();
    }
}

Group::~Group()
{}

} // namespace hdf5
} // namespace nix
<|endoftext|>


<commit_before>#include <json.h>
#include <utf8.h>
#include <string>
#include <functional>
#include <memory>
#include <iostream>

#include "json_object.h"
#include "json_loader.h"
#include "shl_exception.h"

using std::string;
using std::function;
using std::shared_ptr;

namespace shl {

static inline void ensure_utf8(const string& str) {
    if (!utf8::is_valid(str.begin(), str.end())) throw InvalidGrammarException("grammar file contains invalid UTF-8 character");
}

static inline void ensure_object(const json_value* value, const string& msg) {
    if (value->type != json_object) throw InvalidGrammarException(msg);
}

static inline void ensure_string(const json_value* value, const string& msg) {
    if (value->type != json_string) throw InvalidGrammarException(msg);
}

static inline void ensure_array(const json_value* value, const string& msg) {
    if (value->type != json_array) throw InvalidGrammarException(msg);
}

static void for_fields(const json_value* value, function<void(const string&, const json_value*)> process ) {
    for(unsigned int i = 0; i < value->u.object.length; i++) {
        process(value->u.object.values[i].name, value->u.object.values[i].value);
    }
}

static void for_each(const json_value* value, function<void(const json_value*)> process) {
    for(unsigned int i = 0; i < value->u.array.length; i++) {
        process(value->u.array.values[i]);
    }
}

static inline string get_string(const json_value* value) {
    return value->u.string.ptr;
}

static inline map<string, map<string, string> > get_captures(const json_value* value) {
    map<string, map<string, string> > capture_list;

    for_fields(value, [&capture_list](const string& key, const json_value* value) {
        ensure_object(value, "every capture definition should be an object");

        map<string, string>  capture;
        for_fields(value, [&capture](const string& key, const json_value* value) {
            capture[key] = get_string(value);
        });

        capture_list[key] = capture;
    });

    return capture_list;
}

static inline shared_ptr<json_value> parse_json(const string& json) {
    json_value* value = json_parse((const json_char*)json.c_str(), json.size());
    if (value == nullptr) throw InvalidGrammarException("grammar is not a valid json object");
    return shared_ptr<json_value>(value, [](json_value* ptr) { json_value_free(ptr); });
}

JsonObject JsonLoader::load(const string& json) {
    ensure_utf8(json);

    JsonObject object;
    auto value = parse_json(json); // pointer is protected by shared_ptr

    process(object, value.get());

    return object;
}

void JsonLoader::process(JsonObject& root, const json_value* value) {
    ensure_object(value, "grammar definition file should have only one object as root");

    for_fields(value, [&root](const string& key, const json_value* value){
        if (key == "include") {
            ensure_string(value, "include should be a string");
            root.include = get_string(value);

        } else if (key == "scopeName") {
            ensure_string(value, "scopeName should be a string");
            root.scope_name = get_string(value);

        } else if (key == "fileTypes") {
            ensure_array(value, "fileTypes should be array of String");
            for_each(value, [&root](const json_value* value) {
                root.file_types.push_back(get_string(value));
           });

        } else if (key == "name") {
            ensure_string(value, "name should be a string");
            root.name = get_string(value);

        } else if (key == "patterns") {
            ensure_array(value, "patterns should be an array");
            for_each(value, [&root](const json_value* value) {
                ensure_object(value, "patterns can only contains objects");
                JsonObject pattern;
                process(pattern, value);
                root.patterns.push_back(pattern);
            });

        } else if (key == "repository") {
            ensure_object(value, "repository should be a key-value map");
            for_fields(value, [&root](const string& key, const json_value* value){
                ensure_object(value, "repository item can only be an object");
                JsonObject repo_item;
                process(repo_item, value);
                root.repository[key] = repo_item;
            });

        } else if (key == "match") {
            ensure_string(value, "match should be a regex");
            root.match = get_string(value);
        } else if (key == "captures") {
            ensure_object(value, "captures should be an object");
            root.captures = get_captures(value);
        } else if (key == "begin") {
            ensure_string(value, "begin pattern should be a regex");
            root.begin = get_string(value);
        } else if (key == "begin_captures") {
            ensure_object(value, "begin_captures should be an object");
            root.begin_captures = get_captures(value);
        } else if (key == "end") {
            ensure_string(value, "end pattern should be a regex");
            root.end = get_string(value);
        } else if (key == "end_captures") {
            ensure_object(value, "end_captures should be an object");
            root.end_captures = get_captures(value);
        } else if (key == "content_name") {
            ensure_string(value, "content_name should be a string");
            root.content_name = get_string(value);
        }
    });
}

}
<commit_msg>fix wrong object name<commit_after>#include <json.h>
#include <utf8.h>
#include <string>
#include <functional>
#include <memory>
#include <iostream>

#include "json_object.h"
#include "json_loader.h"
#include "shl_exception.h"

using std::string;
using std::function;
using std::shared_ptr;

namespace shl {

static inline void ensure_utf8(const string& str) {
    if (!utf8::is_valid(str.begin(), str.end())) throw InvalidGrammarException("grammar file contains invalid UTF-8 character");
}

static inline void ensure_object(const json_value* value, const string& msg) {
    if (value->type != json_object) throw InvalidGrammarException(msg);
}

static inline void ensure_string(const json_value* value, const string& msg) {
    if (value->type != json_string) throw InvalidGrammarException(msg);
}

static inline void ensure_array(const json_value* value, const string& msg) {
    if (value->type != json_array) throw InvalidGrammarException(msg);
}

static void for_fields(const json_value* value, function<void(const string&, const json_value*)> process ) {
    for(unsigned int i = 0; i < value->u.object.length; i++) {
        process(value->u.object.values[i].name, value->u.object.values[i].value);
    }
}

static void for_each(const json_value* value, function<void(const json_value*)> process) {
    for(unsigned int i = 0; i < value->u.array.length; i++) {
        process(value->u.array.values[i]);
    }
}

static inline string get_string(const json_value* value) {
    return value->u.string.ptr;
}

static inline map<string, map<string, string> > get_captures(const json_value* value) {
    map<string, map<string, string> > capture_list;

    for_fields(value, [&capture_list](const string& key, const json_value* value) {
        ensure_object(value, "every capture definition should be an object");

        map<string, string>  capture;
        for_fields(value, [&capture](const string& key, const json_value* value) {
            capture[key] = get_string(value);
        });

        capture_list[key] = capture;
    });

    return capture_list;
}

static inline shared_ptr<json_value> parse_json(const string& json) {
    json_value* value = json_parse((const json_char*)json.c_str(), json.size());
    if (value == nullptr) throw InvalidGrammarException("grammar is not a valid json object");
    return shared_ptr<json_value>(value, [](json_value* ptr) { json_value_free(ptr); });
}

JsonObject JsonLoader::load(const string& json) {
    ensure_utf8(json);

    JsonObject object;
    auto value = parse_json(json); // pointer is protected by shared_ptr

    process(object, value.get());

    return object;
}

void JsonLoader::process(JsonObject& root, const json_value* value) {
    ensure_object(value, "grammar definition file should have only one object as root");

    for_fields(value, [&root](const string& key, const json_value* value){
        if (key == "include") {
            ensure_string(value, "include should be a string");
            root.include = get_string(value);

        } else if (key == "scopeName") {
            ensure_string(value, "scopeName should be a string");
            root.scope_name = get_string(value);

        } else if (key == "fileTypes") {
            ensure_array(value, "fileTypes should be array of String");
            for_each(value, [&root](const json_value* value) {
                root.file_types.push_back(get_string(value));
           });

        } else if (key == "name") {
            ensure_string(value, "name should be a string");
            root.name = get_string(value);

        } else if (key == "patterns") {
            ensure_array(value, "patterns should be an array");
            for_each(value, [&root](const json_value* value) {
                ensure_object(value, "patterns can only contains objects");
                JsonObject pattern;
                process(pattern, value);
                root.patterns.push_back(pattern);
            });

        } else if (key == "repository") {
            ensure_object(value, "repository should be a key-value map");
            for_fields(value, [&root](const string& key, const json_value* value){
                ensure_object(value, "repository item can only be an object");
                JsonObject repo_item;
                process(repo_item, value);
                root.repository[key] = repo_item;
            });

        } else if (key == "match") {
            ensure_string(value, "match should be a regex");
            root.match = get_string(value);
        } else if (key == "captures") {
            ensure_object(value, "captures should be an object");
            root.captures = get_captures(value);
        } else if (key == "begin") {
            ensure_string(value, "begin pattern should be a regex");
            root.begin = get_string(value);
        } else if (key == "beginCaptures") {
            ensure_object(value, "begin_captures should be an object");
            root.begin_captures = get_captures(value);
        } else if (key == "end") {
            ensure_string(value, "end pattern should be a regex");
            root.end = get_string(value);
        } else if (key == "endCaptures") {
            ensure_object(value, "end_captures should be an object");
            root.end_captures = get_captures(value);
        } else if (key == "contentName") {
            ensure_string(value, "content_name should be a string");
            root.content_name = get_string(value);
        }
    });
}

}
<|endoftext|>


<commit_before>#include <kernel/rtc.hpp>

#include <kernel/os.hpp>
#include <kernel/timers.hpp>
#include <hw/cmos.hpp>
#include <hertz>

using timestamp_t = RTC::timestamp_t;
timestamp_t RTC::booted_at;
timestamp_t RTC::current_time;
uint64_t    RTC::current_ticks;

using namespace std::chrono;

void RTC::init()
{
  // Initialize CMOS
  hw::CMOS::init();

  // set current timestamp and ticks
  current_time  = hw::CMOS::now().to_epoch();
  current_ticks = OS::cycles_since_boot();

  // set boot timestamp
  booted_at = current_time;

  INFO("RTC", "Enabling regular clock sync with CMOS");
  // every minute recalibrate
  Timers::periodic(seconds(60), seconds(60),
  [] (Timers::id_t) {
    static int d = 0;
    printf("One minute passed: %d\n", ++d);
    current_time  = hw::CMOS::now().to_epoch();
    current_ticks = OS::cycles_since_boot();
  });
}

timestamp_t RTC::now()
{
  auto ticks = OS::cycles_since_boot() - current_ticks;
  auto diff  = ticks / Hz(MHz(OS::cpu_freq())).count();

  return current_time + diff;
}
<commit_msg>rtc: Remove debugging output<commit_after>#include <kernel/rtc.hpp>

#include <kernel/os.hpp>
#include <kernel/timers.hpp>
#include <hw/cmos.hpp>
#include <hertz>

using timestamp_t = RTC::timestamp_t;
timestamp_t RTC::booted_at;
timestamp_t RTC::current_time;
uint64_t    RTC::current_ticks;

using namespace std::chrono;

void RTC::init()
{
  // Initialize CMOS
  hw::CMOS::init();

  // set current timestamp and ticks
  current_time  = hw::CMOS::now().to_epoch();
  current_ticks = OS::cycles_since_boot();

  // set boot timestamp
  booted_at = current_time;

  INFO("RTC", "Enabling regular clock sync with CMOS");
  // every minute recalibrate
  Timers::periodic(seconds(60), seconds(60),
  [] (Timers::id_t) {
    current_time  = hw::CMOS::now().to_epoch();
    current_ticks = OS::cycles_since_boot();
  });
}

timestamp_t RTC::now()
{
  auto ticks = OS::cycles_since_boot() - current_ticks;
  auto diff  = ticks / Hz(MHz(OS::cpu_freq())).count();

  return current_time + diff;
}
<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2019, OpenROAD
// All rights reserved.
//
// BSD 3-Clause License
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holder nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////

#include "openroad/OpenRoad.hh"

#include <iostream>

#include "utility/MakeLogger.h"
#include "utility/Logger.h"

#include "opendb/db.h"
#include "opendb/wOrder.h"
#include "opendb/lefin.h"
#include "opendb/defin.h"
#include "opendb/defout.h"

#include "sta/VerilogWriter.hh"
#include "sta/StaMain.hh"

#include "db_sta/dbSta.hh"
#include "db_sta/MakeDbSta.hh"

#include "db_sta/dbReadVerilog.hh"
#include "db_sta/dbNetwork.hh"

#include "openroad/InitOpenRoad.hh"
#include "flute3/flute.h"

#include "init_fp//MakeInitFloorplan.hh"
#include "ioplacer/MakeIoplacer.h"
#include "resizer/MakeResizer.hh"
#include "gui/MakeGui.h"
#include "opendp/MakeOpendp.h"
#include "finale/MakeFinale.h"
#include "tritonmp/MakeTritonMp.h"
#include "replace/MakeReplace.h"
#include "fastroute/MakeFastRoute.h"
#include "tritoncts/MakeTritoncts.h"
#include "tapcell/MakeTapcell.h"
#include "OpenRCX/MakeOpenRCX.h"
#include "triton_route/MakeTritonRoute.h"
#include "pdnsim/MakePDNSim.hh"
#include "antennachecker/MakeAntennaChecker.hh"
#include "PartitionMgr/src/MakePartitionMgr.h"

namespace sta {
extern const char *openroad_tcl_inits[];
}

// Swig uses C linkage for init functions.
extern "C" {
extern int Openroad_Init(Tcl_Interp *interp);
extern int Opendbtcl_Init(Tcl_Interp *interp);
}

// Main.cc set by main()
extern const char* log_filename;
extern const char* metrics_filename;

namespace ord {

using std::min;
using std::max;

using odb::dbLib;
using odb::dbTech;
using odb::dbChip;
using odb::dbDatabase;
using odb::dbBlock;
using odb::Rect;
using odb::Point;

using sta::evalTclInit;
using sta::dbSta;
using sta::Resizer;

OpenRoad::OpenRoad()
  : tcl_interp_(nullptr),
    logger_(nullptr),
    db_(nullptr),
    verilog_network_(nullptr),
    sta_(nullptr),
    resizer_(nullptr),
    ioPlacer_(nullptr),
    opendp_(nullptr),
    finale_(nullptr),
    tritonMp_(nullptr),
    fastRoute_(nullptr),
    tritonCts_(nullptr),
    tapcell_(nullptr),
    extractor_(nullptr),
    detailed_router_(nullptr),
    antenna_checker_(nullptr),
    replace_(nullptr),
    pdnsim_(nullptr),
    partitionMgr_(nullptr)
{
  db_ = dbDatabase::create();
}

OpenRoad::~OpenRoad()
{
  deleteDbVerilogNetwork(verilog_network_);
  deleteDbSta(sta_);
  deleteIoplacer(ioPlacer_);
  deleteResizer(resizer_);
  deleteOpendp(opendp_);
  deleteFastRoute(fastRoute_);
  deleteTritonCts(tritonCts_);
  deleteTapcell(tapcell_);
  deleteTritonMp(tritonMp_);
  deleteOpenRCX(extractor_);
  deleteTritonRoute(detailed_router_);
  deleteReplace(replace_);
  deleteFinale(finale_);
  deleteAntennaChecker(antenna_checker_);
  odb::dbDatabase::destroy(db_);
  deletePartitionMgr(partitionMgr_);
  stt::deleteLUT();
  delete logger_;
}

void
deleteAllMemory()
{
  delete OpenRoad::openRoad();
  sta::Sta::setSta(nullptr);
  sta::deleteAllMemory();
}

sta::dbNetwork *
OpenRoad::getDbNetwork()
{
  return sta_->getDbNetwork();
}

/* static */
OpenRoad *OpenRoad::openRoad()
{
  // This will be destroyed at application exit
  static OpenRoad o;
  return &o;
}

////////////////////////////////////////////////////////////////

void
initOpenRoad(Tcl_Interp *interp)
{
  OpenRoad::openRoad()->init(interp);
}

void
OpenRoad::init(Tcl_Interp *tcl_interp)
{
  tcl_interp_ = tcl_interp;

  // Make components.
  logger_ = makeLogger(log_filename, metrics_filename);
  db_->setLogger(logger_);
  sta_ = makeDbSta();
  verilog_network_ = makeDbVerilogNetwork();
  ioPlacer_ = makeIoplacer();
  resizer_ = makeResizer();
  opendp_ = makeOpendp();
  finale_ = makeFinale();
  fastRoute_ = makeFastRoute();
  tritonCts_ = makeTritonCts();
  tapcell_ = makeTapcell();
  tritonMp_ = makeTritonMp();
  extractor_ = makeOpenRCX();
  detailed_router_ = makeTritonRoute();
  replace_ = makeReplace();
  pdnsim_ = makePDNSim();
  antenna_checker_ = makeAntennaChecker();
  partitionMgr_ = makePartitionMgr();

  // Init components.
  Openroad_Init(tcl_interp);
  // Import TCL scripts.
  evalTclInit(tcl_interp, sta::openroad_tcl_inits);

  initLogger(logger_, tcl_interp);
  initGui(this); // first so we can register our sink with the logger
  Opendbtcl_Init(tcl_interp);
  initInitFloorplan(this);
  stt::readLUT();
  initDbSta(this);
  initResizer(this);
  initDbVerilogNetwork(this);
  initIoplacer(this);
  initReplace(this);
  initOpendp(this);
  initFinale(this);
  initFastRoute(this);
  initTritonCts(this);
  initTapcell(this);
  initTritonMp(this);
  initOpenRCX(this);
  initTritonRoute(this);
  initPDNSim(this);
  initAntennaChecker(this);
  initPartitionMgr(this);

  // Import exported commands to global namespace.
  Tcl_Eval(tcl_interp, "sta::define_sta_cmds");
  Tcl_Eval(tcl_interp, "namespace import sta::*");
}

////////////////////////////////////////////////////////////////

void
OpenRoad::readLef(const char *filename,
		  const char *lib_name,
		  bool make_tech,
		  bool make_library)
{
  odb::lefin lef_reader(db_, logger_, false);
  dbLib *lib = nullptr;
  dbTech *tech = nullptr;
  if (make_tech && make_library) {
    lib = lef_reader.createTechAndLib(lib_name, filename);
    tech = db_->getTech();
  } else if (make_tech) {
    tech = lef_reader.createTech(filename);
  } else if (make_library) {
    lib = lef_reader.createLib(lib_name, filename);
  }

  // both are null on parser failure
  if (lib != nullptr || tech != nullptr) {
    for (Observer* observer : observers_) {
      observer->postReadLef(tech, lib);
    }
  }
}

void
OpenRoad::readDef(const char *filename,
		  bool order_wires,
		  bool continue_on_errors)
{
  odb::defin def_reader(db_,logger_);
  std::vector<odb::dbLib *> search_libs;
  for (odb::dbLib *lib : db_->getLibs())
    search_libs.push_back(lib);
  if (continue_on_errors) {
    def_reader.continueOnErrors();
  }
  dbChip* chip = def_reader.createChip(search_libs, filename);
  if (chip) {
    dbBlock* block = chip->getBlock();
    if (order_wires) {
      odb::orderWires(block,
                      nullptr /* net_name_or_id*/,
                      false /* force */,
                      false /* verbose */,
                      true /* quiet */);
    }

    for (Observer* observer : observers_) {
      observer->postReadDef(block);
    }
  }
}

static odb::defout::Version
stringToDefVersion(string version)
{
  if (version == "5.8")
    return odb::defout::Version::DEF_5_8;
  else if (version == "5.6")
    return odb::defout::Version::DEF_5_6;
  else if (version == "5.5")
    return odb::defout::Version::DEF_5_5;
  else if (version == "5.4")
    return odb::defout::Version::DEF_5_4;
  else if (version == "5.3")
    return odb::defout::Version::DEF_5_3;
  else
    return odb::defout::Version::DEF_5_8;
}

void
OpenRoad::writeDef(const char *filename,
		   string version)
{
  odb::dbChip *chip = db_->getChip();
  if (chip) {
    odb::dbBlock *block = chip->getBlock();
    if (block) {
      odb::defout def_writer(logger_);
      def_writer.setVersion(stringToDefVersion(version));
      def_writer.writeBlock(block, filename);
    }
  }
}

void
OpenRoad::readDb(const char *filename)
{
  FILE *stream = fopen(filename, "r");
  if (stream == nullptr) {
    return;
  }

  db_->read(stream);
  fclose(stream);

  for (Observer* observer : observers_) {
    observer->postReadDb(db_);
  }
}

void
OpenRoad::writeDb(const char *filename)
{
  FILE *stream = fopen(filename, "w");
  if (stream) {
    db_->write(stream);
    fclose(stream);
  }
}

void
OpenRoad::readVerilog(const char *filename)
{
  dbReadVerilog(filename, verilog_network_);
}

void
OpenRoad::linkDesign(const char *design_name)

{
  dbLinkDesign(design_name, verilog_network_, db_, logger_);
  for (Observer* observer : observers_) {
    observer->postReadDb(db_);
  }
}

void
OpenRoad::writeVerilog(const char *filename,
		       bool sort,
		       bool include_pwr_gnd,
		       std::vector<sta::LibertyCell*> *remove_cells)
{
  sta::writeVerilog(filename, sort, include_pwr_gnd,
		    remove_cells, sta_->network());
}

bool
OpenRoad::unitsInitialized()
{
  // Units are set by the first liberty library read.
  return getDbNetwork()->defaultLibertyLibrary() != nullptr;
}

odb::Rect
OpenRoad::getCore()
{
  return ord::getCore(db_->getChip()->getBlock());
}

void OpenRoad::addObserver(Observer *observer)
{
  assert(observer->owner_ == nullptr);
  observer->owner_ = this;
  observers_.insert(observer);
}

void OpenRoad::removeObserver(Observer *observer)
{
  observer->owner_ = nullptr;
  observers_.erase(observer);
}

OpenRoad::Observer::~Observer()
{
  if (owner_) {
    owner_->removeObserver(this);
  }
}

////////////////////////////////////////////////////////////////

// Need a header for these functions cherry uses in
// InitFloorplan, Resizer, OpenDP.

Rect
getCore(dbBlock *block)
{
  odb::Rect core;
  block->getCoreArea(core);
  return core;
}

// Return the point inside rect that is closest to pt.
Point
closestPtInRect(Rect rect,
		Point pt)
{
  return Point(min(max(pt.getX(), rect.xMin()), rect.xMax()),
               min(max(pt.getY(), rect.yMin()), rect.yMax()));
}

Point
closestPtInRect(Rect rect,
		int x,
		int y)
{
  return Point(min(max(x, rect.xMin()), rect.xMax()),
               min(max(y, rect.yMin()), rect.yMax()));
}

} // namespace
<commit_msg>temporarily disable grt & gpl destruction while they are being debugged<commit_after>/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2019, OpenROAD
// All rights reserved.
//
// BSD 3-Clause License
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holder nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////

#include "openroad/OpenRoad.hh"

#include <iostream>

#include "utility/MakeLogger.h"
#include "utility/Logger.h"

#include "opendb/db.h"
#include "opendb/wOrder.h"
#include "opendb/lefin.h"
#include "opendb/defin.h"
#include "opendb/defout.h"

#include "sta/VerilogWriter.hh"
#include "sta/StaMain.hh"

#include "db_sta/dbSta.hh"
#include "db_sta/MakeDbSta.hh"

#include "db_sta/dbReadVerilog.hh"
#include "db_sta/dbNetwork.hh"

#include "openroad/InitOpenRoad.hh"
#include "flute3/flute.h"

#include "init_fp//MakeInitFloorplan.hh"
#include "ioplacer/MakeIoplacer.h"
#include "resizer/MakeResizer.hh"
#include "gui/MakeGui.h"
#include "opendp/MakeOpendp.h"
#include "finale/MakeFinale.h"
#include "tritonmp/MakeTritonMp.h"
#include "replace/MakeReplace.h"
#include "fastroute/MakeFastRoute.h"
#include "tritoncts/MakeTritoncts.h"
#include "tapcell/MakeTapcell.h"
#include "OpenRCX/MakeOpenRCX.h"
#include "triton_route/MakeTritonRoute.h"
#include "pdnsim/MakePDNSim.hh"
#include "antennachecker/MakeAntennaChecker.hh"
#include "PartitionMgr/src/MakePartitionMgr.h"

namespace sta {
extern const char *openroad_tcl_inits[];
}

// Swig uses C linkage for init functions.
extern "C" {
extern int Openroad_Init(Tcl_Interp *interp);
extern int Opendbtcl_Init(Tcl_Interp *interp);
}

// Main.cc set by main()
extern const char* log_filename;
extern const char* metrics_filename;

namespace ord {

using std::min;
using std::max;

using odb::dbLib;
using odb::dbTech;
using odb::dbChip;
using odb::dbDatabase;
using odb::dbBlock;
using odb::Rect;
using odb::Point;

using sta::evalTclInit;
using sta::dbSta;
using sta::Resizer;

OpenRoad::OpenRoad()
  : tcl_interp_(nullptr),
    logger_(nullptr),
    db_(nullptr),
    verilog_network_(nullptr),
    sta_(nullptr),
    resizer_(nullptr),
    ioPlacer_(nullptr),
    opendp_(nullptr),
    finale_(nullptr),
    tritonMp_(nullptr),
    fastRoute_(nullptr),
    tritonCts_(nullptr),
    tapcell_(nullptr),
    extractor_(nullptr),
    detailed_router_(nullptr),
    antenna_checker_(nullptr),
    replace_(nullptr),
    pdnsim_(nullptr),
    partitionMgr_(nullptr)
{
  db_ = dbDatabase::create();
}

OpenRoad::~OpenRoad()
{
  deleteDbVerilogNetwork(verilog_network_);
  deleteDbSta(sta_);
  deleteIoplacer(ioPlacer_);
  deleteResizer(resizer_);
  deleteOpendp(opendp_);
  // deleteFastRoute(fastRoute_);
  deleteTritonCts(tritonCts_);
  deleteTapcell(tapcell_);
  deleteTritonMp(tritonMp_);
  deleteOpenRCX(extractor_);
  deleteTritonRoute(detailed_router_);
  // deleteReplace(replace_);
  deleteFinale(finale_);
  deleteAntennaChecker(antenna_checker_);
  odb::dbDatabase::destroy(db_);
  deletePartitionMgr(partitionMgr_);
  stt::deleteLUT();
  delete logger_;
}

void
deleteAllMemory()
{
  delete OpenRoad::openRoad();
  sta::Sta::setSta(nullptr);
  sta::deleteAllMemory();
}

sta::dbNetwork *
OpenRoad::getDbNetwork()
{
  return sta_->getDbNetwork();
}

/* static */
OpenRoad *OpenRoad::openRoad()
{
  // This will be destroyed at application exit
  static OpenRoad o;
  return &o;
}

////////////////////////////////////////////////////////////////

void
initOpenRoad(Tcl_Interp *interp)
{
  OpenRoad::openRoad()->init(interp);
}

void
OpenRoad::init(Tcl_Interp *tcl_interp)
{
  tcl_interp_ = tcl_interp;

  // Make components.
  logger_ = makeLogger(log_filename, metrics_filename);
  db_->setLogger(logger_);
  sta_ = makeDbSta();
  verilog_network_ = makeDbVerilogNetwork();
  ioPlacer_ = makeIoplacer();
  resizer_ = makeResizer();
  opendp_ = makeOpendp();
  finale_ = makeFinale();
  fastRoute_ = makeFastRoute();
  tritonCts_ = makeTritonCts();
  tapcell_ = makeTapcell();
  tritonMp_ = makeTritonMp();
  extractor_ = makeOpenRCX();
  detailed_router_ = makeTritonRoute();
  replace_ = makeReplace();
  pdnsim_ = makePDNSim();
  antenna_checker_ = makeAntennaChecker();
  partitionMgr_ = makePartitionMgr();

  // Init components.
  Openroad_Init(tcl_interp);
  // Import TCL scripts.
  evalTclInit(tcl_interp, sta::openroad_tcl_inits);

  initLogger(logger_, tcl_interp);
  initGui(this); // first so we can register our sink with the logger
  Opendbtcl_Init(tcl_interp);
  initInitFloorplan(this);
  stt::readLUT();
  initDbSta(this);
  initResizer(this);
  initDbVerilogNetwork(this);
  initIoplacer(this);
  initReplace(this);
  initOpendp(this);
  initFinale(this);
  initFastRoute(this);
  initTritonCts(this);
  initTapcell(this);
  initTritonMp(this);
  initOpenRCX(this);
  initTritonRoute(this);
  initPDNSim(this);
  initAntennaChecker(this);
  initPartitionMgr(this);

  // Import exported commands to global namespace.
  Tcl_Eval(tcl_interp, "sta::define_sta_cmds");
  Tcl_Eval(tcl_interp, "namespace import sta::*");
}

////////////////////////////////////////////////////////////////

void
OpenRoad::readLef(const char *filename,
		  const char *lib_name,
		  bool make_tech,
		  bool make_library)
{
  odb::lefin lef_reader(db_, logger_, false);
  dbLib *lib = nullptr;
  dbTech *tech = nullptr;
  if (make_tech && make_library) {
    lib = lef_reader.createTechAndLib(lib_name, filename);
    tech = db_->getTech();
  } else if (make_tech) {
    tech = lef_reader.createTech(filename);
  } else if (make_library) {
    lib = lef_reader.createLib(lib_name, filename);
  }

  // both are null on parser failure
  if (lib != nullptr || tech != nullptr) {
    for (Observer* observer : observers_) {
      observer->postReadLef(tech, lib);
    }
  }
}

void
OpenRoad::readDef(const char *filename,
		  bool order_wires,
		  bool continue_on_errors)
{
  odb::defin def_reader(db_,logger_);
  std::vector<odb::dbLib *> search_libs;
  for (odb::dbLib *lib : db_->getLibs())
    search_libs.push_back(lib);
  if (continue_on_errors) {
    def_reader.continueOnErrors();
  }
  dbChip* chip = def_reader.createChip(search_libs, filename);
  if (chip) {
    dbBlock* block = chip->getBlock();
    if (order_wires) {
      odb::orderWires(block,
                      nullptr /* net_name_or_id*/,
                      false /* force */,
                      false /* verbose */,
                      true /* quiet */);
    }

    for (Observer* observer : observers_) {
      observer->postReadDef(block);
    }
  }
}

static odb::defout::Version
stringToDefVersion(string version)
{
  if (version == "5.8")
    return odb::defout::Version::DEF_5_8;
  else if (version == "5.6")
    return odb::defout::Version::DEF_5_6;
  else if (version == "5.5")
    return odb::defout::Version::DEF_5_5;
  else if (version == "5.4")
    return odb::defout::Version::DEF_5_4;
  else if (version == "5.3")
    return odb::defout::Version::DEF_5_3;
  else
    return odb::defout::Version::DEF_5_8;
}

void
OpenRoad::writeDef(const char *filename,
		   string version)
{
  odb::dbChip *chip = db_->getChip();
  if (chip) {
    odb::dbBlock *block = chip->getBlock();
    if (block) {
      odb::defout def_writer(logger_);
      def_writer.setVersion(stringToDefVersion(version));
      def_writer.writeBlock(block, filename);
    }
  }
}

void
OpenRoad::readDb(const char *filename)
{
  FILE *stream = fopen(filename, "r");
  if (stream == nullptr) {
    return;
  }

  db_->read(stream);
  fclose(stream);

  for (Observer* observer : observers_) {
    observer->postReadDb(db_);
  }
}

void
OpenRoad::writeDb(const char *filename)
{
  FILE *stream = fopen(filename, "w");
  if (stream) {
    db_->write(stream);
    fclose(stream);
  }
}

void
OpenRoad::readVerilog(const char *filename)
{
  dbReadVerilog(filename, verilog_network_);
}

void
OpenRoad::linkDesign(const char *design_name)

{
  dbLinkDesign(design_name, verilog_network_, db_, logger_);
  for (Observer* observer : observers_) {
    observer->postReadDb(db_);
  }
}

void
OpenRoad::writeVerilog(const char *filename,
		       bool sort,
		       bool include_pwr_gnd,
		       std::vector<sta::LibertyCell*> *remove_cells)
{
  sta::writeVerilog(filename, sort, include_pwr_gnd,
		    remove_cells, sta_->network());
}

bool
OpenRoad::unitsInitialized()
{
  // Units are set by the first liberty library read.
  return getDbNetwork()->defaultLibertyLibrary() != nullptr;
}

odb::Rect
OpenRoad::getCore()
{
  return ord::getCore(db_->getChip()->getBlock());
}

void OpenRoad::addObserver(Observer *observer)
{
  assert(observer->owner_ == nullptr);
  observer->owner_ = this;
  observers_.insert(observer);
}

void OpenRoad::removeObserver(Observer *observer)
{
  observer->owner_ = nullptr;
  observers_.erase(observer);
}

OpenRoad::Observer::~Observer()
{
  if (owner_) {
    owner_->removeObserver(this);
  }
}

////////////////////////////////////////////////////////////////

// Need a header for these functions cherry uses in
// InitFloorplan, Resizer, OpenDP.

Rect
getCore(dbBlock *block)
{
  odb::Rect core;
  block->getCoreArea(core);
  return core;
}

// Return the point inside rect that is closest to pt.
Point
closestPtInRect(Rect rect,
		Point pt)
{
  return Point(min(max(pt.getX(), rect.xMin()), rect.xMax()),
               min(max(pt.getY(), rect.yMin()), rect.yMax()));
}

Point
closestPtInRect(Rect rect,
		int x,
		int y)
{
  return Point(min(max(x, rect.xMin()), rect.xMax()),
               min(max(y, rect.yMin()), rect.yMax()));
}

} // namespace
<|endoftext|>