1251881Speter/* 2251881Speter * eol.c : generic eol/keyword routines 3251881Speter * 4251881Speter * ==================================================================== 5251881Speter * Licensed to the Apache Software Foundation (ASF) under one 6251881Speter * or more contributor license agreements. See the NOTICE file 7251881Speter * distributed with this work for additional information 8251881Speter * regarding copyright ownership. The ASF licenses this file 9251881Speter * to you under the Apache License, Version 2.0 (the 10251881Speter * "License"); you may not use this file except in compliance 11251881Speter * with the License. You may obtain a copy of the License at 12251881Speter * 13251881Speter * http://www.apache.org/licenses/LICENSE-2.0 14251881Speter * 15251881Speter * Unless required by applicable law or agreed to in writing, 16251881Speter * software distributed under the License is distributed on an 17251881Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18251881Speter * KIND, either express or implied. See the License for the 19251881Speter * specific language governing permissions and limitations 20251881Speter * under the License. 21251881Speter * ==================================================================== 22251881Speter */ 23251881Speter 24251881Speter 25251881Speter 26251881Speter#define APR_WANT_STRFUNC 27251881Speter 28251881Speter#include <apr_file_io.h> 29251881Speter#include "svn_io.h" 30251881Speter#include "private/svn_eol_private.h" 31251881Speter#include "private/svn_dep_compat.h" 32251881Speter 33251881Speterchar * 34251881Spetersvn_eol__find_eol_start(char *buf, apr_size_t len) 35251881Speter{ 36299742Sdim#if SVN_UNALIGNED_ACCESS_IS_OK 37251881Speter 38251881Speter /* Scan the input one machine word at a time. */ 39251881Speter for (; len > sizeof(apr_uintptr_t) 40251881Speter ; buf += sizeof(apr_uintptr_t), len -= sizeof(apr_uintptr_t)) 41251881Speter { 42251881Speter /* This is a variant of the well-known strlen test: */ 43251881Speter apr_uintptr_t chunk = *(const apr_uintptr_t *)buf; 44251881Speter 45251881Speter /* A byte in SVN__R_TEST is \0, iff it was \r in *BUF. 46251881Speter * Similarly, SVN__N_TEST is an indicator for \n. */ 47251881Speter apr_uintptr_t r_test = chunk ^ SVN__R_MASK; 48251881Speter apr_uintptr_t n_test = chunk ^ SVN__N_MASK; 49251881Speter 50299742Sdim /* A byte in SVN__R_TEST can only be < 0x80, iff it has been \0 before 51299742Sdim * (i.e. \r in *BUF). Ditto for SVN__N_TEST. */ 52251881Speter r_test |= (r_test & SVN__LOWER_7BITS_SET) + SVN__LOWER_7BITS_SET; 53251881Speter n_test |= (n_test & SVN__LOWER_7BITS_SET) + SVN__LOWER_7BITS_SET; 54251881Speter 55251881Speter /* Check whether at least one of the words contains a byte <0x80 56251881Speter * (if one is detected, there was a \r or \n in CHUNK). */ 57251881Speter if ((r_test & n_test & SVN__BIT_7_SET) != SVN__BIT_7_SET) 58251881Speter break; 59251881Speter } 60251881Speter 61299742Sdim#endif 62299742Sdim 63251881Speter /* The remaining odd bytes will be examined the naive way: */ 64251881Speter for (; len > 0; ++buf, --len) 65251881Speter { 66251881Speter if (*buf == '\n' || *buf == '\r') 67251881Speter return buf; 68251881Speter } 69251881Speter 70251881Speter return NULL; 71251881Speter} 72251881Speter 73251881Speterconst char * 74251881Spetersvn_eol__detect_eol(char *buf, apr_size_t len, char **eolp) 75251881Speter{ 76251881Speter char *eol; 77251881Speter 78251881Speter eol = svn_eol__find_eol_start(buf, len); 79251881Speter if (eol) 80251881Speter { 81251881Speter if (eolp) 82251881Speter *eolp = eol; 83251881Speter 84251881Speter if (*eol == '\n') 85251881Speter return "\n"; 86251881Speter 87251881Speter /* We found a CR. */ 88251881Speter ++eol; 89251881Speter if (eol == buf + len || *eol != '\n') 90251881Speter return "\r"; 91251881Speter return "\r\n"; 92251881Speter } 93251881Speter 94251881Speter return NULL; 95251881Speter} 96