// file : odb/statement-processingc-common.hxx // copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC // license : GNU GPL v2; see accompanying LICENSE file #ifndef ODB_STATEMENT_PROCESSING_COMMON_HXX #define ODB_STATEMENT_PROCESSING_COMMON_HXX #include //#define LIBODB_DEBUG_STATEMENT_PROCESSING 1 //#define LIBODB_TRACE_STATEMENT_PROCESSING 1 #include #include // std::size_t namespace odb { typedef std::char_traits traits; static inline const char* find (const char* b, const char* e, char c) { return traits::find (b, e - b, c); } static inline const char* rfind (const char* b, const char* e, char c) { for (--e; b != e; --e) if (*e == c) return e; return 0; } // Iterate over INSERT column/value list, UPDATE SET expression list, // or SELECT column/join list. // // for (const char* b (columns_begin), *e (begin (b, end)); // e != 0; // next (b, e, end)) // { // // b points to the beginning of the value (i.e., one past '('). // // e points one past the end of the value (i.e., to ',', ')', or '\n'). // } // // // b points one past the last value. // static inline const char* paren_begin (const char*& b, const char* end) { // Note that the list may not end with '\n'. b++; // Skip '('. const char* e (find (b, end, '\n')); return (e != 0 ? e : end) - 1; // Skip ',' or ')'. } static inline void paren_next (const char*& b, const char*& e, const char* end) { if (*e == ',') { b = e + 2; // Skip past '\n'. e = find (b, end, '\n'); e = (e != 0 ? e : end) - 1; // Skip ',' or ')'. } else { b = (e + 1 != end ? e + 2 : end); // Skip past '\n'. e = 0; } } static inline const char* comma_begin (const char* b, const char* end) { // Note that the list may not end with '\n'. const char* e (find (b, end, '\n')); return e != 0 ? e - (*(e - 1) == ',' ? 1 : 0) : end; // Skip ','. } static inline void comma_next (const char*& b, const char*& e, const char* end) { if (*e == ',') { b = e + 2; // Skip past '\n'. e = find (b, end, '\n'); e = (e != 0 ? e - (*(e - 1) == ',' ? 1 : 0) : end); // Skip ','. } else { b = (e != end ? e + 1 : end); // Skip past '\n'. e = 0; } } static inline const char* newline_begin (const char* b, const char* end) { // Note that the list may not end with '\n'. const char* e (find (b, end, '\n')); return e != 0 ? e : end; } static inline void newline_next (const char*& b, const char*& e, const char* end, const char* prefix, std::size_t prefix_size) { if (e != end) e++; // Skip past '\n'. b = e; // Do we have another element? // if (static_cast (end - b) > prefix_size && traits::compare (b, prefix, prefix_size) == 0) { e = find (b, end, '\n'); if (e == 0) e = end; } else e = 0; } // Note that end must point to the beginning of the list. // static inline const char* newline_rbegin (const char* e, const char* end) { const char* b (rfind (end, e - 1, '\n')); return b != 0 ? b + 1 : end; // Skip past '\n'. } static inline void newline_rnext (const char*& b, const char*& e, const char* end) { if (b != end) { e = b - 1; // Skip to previous '\n'. b = rfind (end, e - 1, '\n'); b = (b != 0 ? b + 1 : end); // Skip past '\n'. } else { e = end - 1; // One before the first element. b = 0; } } // Fast path: just remove the "structure". // static inline void process_fast (const char* s, std::string& r) { r = s; for (std::size_t i (r.find ('\n')); i != std::string::npos; i = r.find ('\n', i)) r[i++] = ' '; } } #include #endif // ODB_STATEMENT_PROCESSING_COMMON_HXX