aboutsummaryrefslogtreecommitdiffstats
path: root/generic/viaduct/fabulous/fabric_parsing.h
diff options
context:
space:
mode:
Diffstat (limited to 'generic/viaduct/fabulous/fabric_parsing.h')
-rw-r--r--generic/viaduct/fabulous/fabric_parsing.h175
1 files changed, 175 insertions, 0 deletions
diff --git a/generic/viaduct/fabulous/fabric_parsing.h b/generic/viaduct/fabulous/fabric_parsing.h
new file mode 100644
index 00000000..3fa263ca
--- /dev/null
+++ b/generic/viaduct/fabulous/fabric_parsing.h
@@ -0,0 +1,175 @@
+/*
+ * nextpnr -- Next Generation Place and Route
+ *
+ * Copyright (C) 2022 gatecat <gatecat@ds0.me>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef FABULOUS_PARSING_H
+#define FABULOUS_PARSING_H
+
+#include <iostream>
+#include <limits>
+#include <string>
+#include "idstring.h"
+#include "nextpnr_assertions.h"
+#include "nextpnr_namespaces.h"
+
+NEXTPNR_NAMESPACE_BEGIN
+
+struct BaseCtx;
+
+// Lightweight NIH string_view
+struct parser_view
+{
+ char *m_ptr;
+ size_t m_length;
+ parser_view() : m_ptr(nullptr), m_length(0){};
+ explicit parser_view(std::string &str) : m_ptr(&(str[0])), m_length(str.size()){};
+ parser_view(char *ptr, size_t length) : m_ptr(ptr), m_length(length){};
+
+ static constexpr size_t npos = std::numeric_limits<size_t>::max();
+ char operator[](size_t idx)
+ {
+ NPNR_ASSERT(idx < m_length);
+ return m_ptr[idx];
+ }
+
+ size_t size() const { return m_length; }
+
+ bool empty() const { return m_length == 0; }
+
+ parser_view substr(size_t start, size_t length = npos)
+ {
+ NPNR_ASSERT(start <= m_length);
+ if (length == npos)
+ length = m_length - start;
+ NPNR_ASSERT(length <= m_length);
+ return parser_view(m_ptr + start, length);
+ }
+
+ size_t find(char tok) const
+ {
+ for (size_t i = 0; i < m_length; i++)
+ if (m_ptr[i] == tok)
+ return i;
+ return npos;
+ }
+
+ IdString to_id(const BaseCtx *ctx)
+ {
+ // This isn't really ideal, let's hope one day we can move to C++20 and have proper string_views instead :3
+ char tmp = m_ptr[m_length];
+ m_ptr[m_length] = '\0';
+ IdString id = IdString(ctx, m_ptr);
+ m_ptr[m_length] = tmp;
+ return id;
+ }
+
+ long to_int()
+ {
+ // This isn't really ideal, let's hope one day we can move to C++20 and have proper string_views instead :3
+ char tmp = m_ptr[m_length];
+ m_ptr[m_length] = '\0';
+ long l = strtol(m_ptr, nullptr, 0);
+ m_ptr[m_length] = tmp;
+ return l;
+ }
+
+ parser_view strip(const std::string &ws = " \r\n\t")
+ {
+ char *ptr = m_ptr;
+ size_t length = m_length;
+ while (length > 0) { // strip front
+ if (ws.find(*ptr) == std::string::npos) // not whitespace
+ break;
+ ptr++;
+ length--;
+ }
+ while (length > 0) { // strip back
+ if (ws.find(ptr[length - 1]) == std::string::npos) // not whitespace
+ break;
+ length--;
+ }
+ return parser_view(ptr, length);
+ }
+
+ char back()
+ {
+ NPNR_ASSERT(m_length > 0);
+ return m_ptr[m_length - 1];
+ }
+
+ parser_view back(size_t count)
+ {
+ NPNR_ASSERT(count <= m_length);
+ return parser_view(m_ptr + (m_length - count), count);
+ }
+
+ bool starts_with(const std::string &st)
+ {
+ if (m_length < st.size())
+ return false;
+ for (size_t i = 0; i < st.length(); i++)
+ if (m_ptr[i] != st[i])
+ return false;
+ return true;
+ }
+ std::pair<parser_view, parser_view> split(char delim) const
+ {
+ size_t pos = find(delim);
+ NPNR_ASSERT(pos != npos);
+ return std::make_pair(parser_view(m_ptr, pos), parser_view(m_ptr + pos + 1, m_length - (pos + 1)));
+ }
+};
+
+struct CsvParser
+{
+ explicit CsvParser(std::istream &in) : in(in){};
+ std::istream &in;
+ std::string buf;
+ parser_view view;
+ bool fetch_next_line()
+ {
+ while (!in.eof()) {
+ std::getline(in, buf);
+ view = parser_view(buf).strip();
+ size_t end_pos = view.find('#');
+ if (end_pos != parser_view::npos)
+ view = view.substr(0, end_pos);
+ view = view.strip();
+ if (!view.empty())
+ return true;
+ }
+ return false;
+ }
+ parser_view next_field()
+ {
+ size_t next_delim = view.find(',');
+ if (next_delim == parser_view::npos) {
+ parser_view result = view.substr(0, next_delim);
+ view = parser_view();
+ return result;
+ } else {
+ parser_view result = view.substr(0, next_delim);
+ view = view.substr(next_delim + 1);
+ return result;
+ }
+ }
+};
+
+NEXTPNR_NAMESPACE_END
+
+#endif